File: session_store.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (199 lines) | stat: -rw-r--r-- 8,505 bytes parent folder | download | duplicates (6)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_
#define COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/data_type_store.h"
#include "components/sync/model/metadata_batch.h"
#include "components/sync/model/model_error.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_sessions/synced_session_tracker.h"

namespace sync_sessions {

// Class responsible for maintaining an in-memory representation of sync
// sessions (by owning a SyncedSessionTracker) with the capability to persist
// state to disk and restore (data and metadata). The API enforces a valid and
// consistent state of the model, e.g. by making sure there is at most one sync
// entity per client tag.
class SessionStore {
 public:
  struct SessionInfo {
    std::string session_tag;
    std::string client_name;
    sync_pb::SyncEnums::DeviceType device_type = sync_pb::SyncEnums::TYPE_UNSET;
    syncer::DeviceInfo::FormFactor device_form_factor =
        syncer::DeviceInfo::FormFactor::kUnknown;
  };

  using OpenCallback = base::OnceCallback<void(
      const std::optional<syncer::ModelError>& error,
      std::unique_ptr<SessionStore> store,
      std::unique_ptr<syncer::MetadataBatch> metadata_batch)>;

  // Opens a SessionStore instance, which involves IO to load previous state
  // from disk. |sessions_client| must not be null and must outlive the
  // SessionStore instance returned via |callback|, or until the callback is
  // cancelled.
  static void Open(const std::string& cache_guid,
                   SyncSessionsClient* sessions_client,
                   OpenCallback callback);

  // Verifies whether a proto is malformed (e.g. required fields are missing).
  static bool AreValidSpecifics(const sync_pb::SessionSpecifics& specifics);
  // |specifics| must be valid, see AreValidSpecifics().
  static std::string GetClientTag(const sync_pb::SessionSpecifics& specifics);
  // |specifics| must be valid, see AreValidSpecifics().
  static std::string GetStorageKey(const sync_pb::SessionSpecifics& specifics);
  static std::string GetHeaderStorageKey(const std::string& session_tag);
  static std::string GetTabStorageKey(const std::string& session_tag,
                                      int tab_node_id);
  // Verifies if |storage_key| corresponds to an entity in the local session,
  // identified by the session tag.
  bool StorageKeyMatchesLocalSession(const std::string& storage_key) const;

  // Various equivalents for testing.
  static std::string GetTabClientTagForTest(const std::string& session_tag,
                                            int tab_node_id);

  // Similar to DataTypeStore::WriteBatch but enforces a consistent state. In
  // the current implementation, some functions do *NOT* update the tracker, so
  // callers are responsible for doing so.
  // TODO(crbug.com/41295474): Enforce consistency between in-memory and
  // persisted data by always updating the tracker.
  class WriteBatch {
   public:
    // Callback that mimics the signature of DataTypeStore::CommitWriteBatch().
    using CommitCallback = base::OnceCallback<void(
        std::unique_ptr<syncer::DataTypeStore::WriteBatch>,
        syncer::DataTypeStore::CallbackWithResult)>;

    // Raw pointers must not be nullptr and must outlive this object.
    WriteBatch(std::unique_ptr<syncer::DataTypeStore::WriteBatch> batch,
               CommitCallback commit_cb,
               syncer::OnceModelErrorHandler error_handler,
               SyncedSessionTracker* session_tracker);

    WriteBatch(const WriteBatch&) = delete;
    WriteBatch& operator=(const WriteBatch&) = delete;

    ~WriteBatch();

    // Most mutations below return storage keys.
    std::string PutAndUpdateTracker(const sync_pb::SessionSpecifics& specifics,
                                    base::Time modification_time);
    // Returns all deleted storage keys, which may be more than one if
    // |storage_key| refers to a header entity.
    std::vector<std::string> DeleteForeignEntityAndUpdateTracker(
        const std::string& storage_key);
    // The functions below do not update SyncedSessionTracker and hence it is
    // the caller's responsibility to do so *before* calling these functions.
    std::string PutWithoutUpdatingTracker(
        const sync_pb::SessionSpecifics& specifics);
    std::string DeleteLocalTabWithoutUpdatingTracker(int tab_node_id);

    syncer::MetadataChangeList* GetMetadataChangeList();

    static void Commit(std::unique_ptr<WriteBatch> batch);

   private:
    std::unique_ptr<syncer::DataTypeStore::WriteBatch> batch_;
    CommitCallback commit_cb_;
    syncer::OnceModelErrorHandler error_handler_;
    const raw_ptr<SyncedSessionTracker> session_tracker_;
  };

  SessionStore(const SessionStore&) = delete;
  SessionStore& operator=(const SessionStore&) = delete;

  ~SessionStore();

  const SessionInfo& local_session_info() const { return local_session_info_; }

  // Converts the in-memory model (SyncedSessionTracker) of sessions to sync
  // protos.
  std::unique_ptr<syncer::DataBatch> GetSessionDataForKeys(
      const std::vector<std::string>& storage_keys) const;

  // Returns all known session entities, local and foreign, generated from the
  // in-memory model (SyncedSessionTracker).
  std::unique_ptr<syncer::DataBatch> GetAllSessionData() const;

  // Write API. WriteBatch instances must not outlive this store and must be
  // committed prior to destruction. Besides, more than one uncommitted
  // instance must not exist at any time.
  std::unique_ptr<WriteBatch> CreateWriteBatch(
      syncer::OnceModelErrorHandler error_handler);

  using RecreateEmptyStoreCallback =
      base::OnceCallback<std::unique_ptr<SessionStore>(
          const std::string& cache_guid,
          SyncSessionsClient* sessions_client)>;

  // Deletes all data and metadata from the `session_store` and destroys it.
  // Returns a callback that allows synchronously re-creating an empty
  // SessionStore, by reusing the underlying DataTypeStore.
  static RecreateEmptyStoreCallback DeleteAllDataAndMetadata(
      std::unique_ptr<SessionStore> session_store);

  // TODO(crbug.com/41295474): Avoid exposing a mutable tracker, because that
  // bypasses the consistency-enforcing API.
  SyncedSessionTracker* mutable_tracker() { return &session_tracker_; }
  const SyncedSessionTracker* tracker() const { return &session_tracker_; }

 private:
  // Helper class used to collect all parameters needed by the constructor.
  struct Builder;

  static void OnStoreCreated(
      std::unique_ptr<Builder> builder,
      const std::optional<syncer::ModelError>& error,
      std::unique_ptr<syncer::DataTypeStore> underlying_store);
  static void OnReadAllMetadata(
      std::unique_ptr<Builder> builder,
      const std::optional<syncer::ModelError>& error,
      std::unique_ptr<syncer::MetadataBatch> metadata_batch);
  static void OnReadAllData(std::unique_ptr<Builder> builder,
                            const std::optional<syncer::ModelError>& error);

  static std::unique_ptr<SessionStore> RecreateEmptyStore(
      SessionInfo local_session_info_without_session_tag,
      std::unique_ptr<syncer::DataTypeStore> underlying_store,
      const std::string& cache_guid,
      SyncSessionsClient* sessions_client);

  // |sessions_client| must not be null and must outlive this object.
  SessionStore(const SessionInfo& local_session_info,
               std::unique_ptr<syncer::DataTypeStore> underlying_store,
               std::map<std::string, sync_pb::SessionSpecifics> initial_data,
               const syncer::EntityMetadataMap& initial_metadata,
               SyncSessionsClient* sessions_client);

  const SessionInfo local_session_info_;

  // In charge of actually persisting changes to disk.
  std::unique_ptr<syncer::DataTypeStore> store_;

  const raw_ptr<SyncSessionsClient> sessions_client_;

  SyncedSessionTracker session_tracker_;

  base::WeakPtrFactory<SessionStore> weak_ptr_factory_{this};
};

}  // namespace sync_sessions

#endif  // COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_