| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // 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 <string> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "components/sync/model/data_batch.h" |
| #include "components/sync/model/model_error.h" |
| #include "components/sync/model/model_type_store.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; |
| }; |
| |
| using OpenCallback = base::OnceCallback<void( |
| const base::Optional<syncer::ModelError>& error, |
| std::unique_ptr<SessionStore> store, |
| std::unique_ptr<syncer::MetadataBatch> metadata_batch)>; |
| // Mimics signature of FaviconCache::UpdateMappingsFromForeignTab(). |
| using RestoredForeignTabCallback = |
| base::RepeatingCallback<void(const sync_pb::SessionTab&, base::Time)>; |
| |
| // 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, |
| const RestoredForeignTabCallback& restored_foreign_tab_callback, |
| 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 ModelTypeStore::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/681921): Enforce consistency between in-memory and persisted |
| // data by always updating the tracker. |
| class WriteBatch { |
| public: |
| // Callback that mimics the signature of ModelTypeStore::CommitWriteBatch(). |
| using CommitCallback = base::OnceCallback<void( |
| std::unique_ptr<syncer::ModelTypeStore::WriteBatch>, |
| syncer::ModelTypeStore::CallbackWithResult)>; |
| |
| // Raw pointers must not be nullptr and must outlive this object. |
| WriteBatch(std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch, |
| CommitCallback commit_cb, |
| syncer::OnceModelErrorHandler error_handler, |
| SyncedSessionTracker* session_tracker); |
| ~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::ModelTypeStore::WriteBatch> batch_; |
| CommitCallback commit_cb_; |
| syncer::OnceModelErrorHandler error_handler_; |
| SyncedSessionTracker* const session_tracker_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WriteBatch); |
| }; |
| |
| ~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); |
| void DeleteAllDataAndMetadata(); |
| |
| // TODO(crbug.com/681921): 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 base::Optional<syncer::ModelError>& error, |
| std::unique_ptr<syncer::ModelTypeStore> underlying_store); |
| static void OnReadAllMetadata( |
| std::unique_ptr<Builder> builder, |
| const base::Optional<syncer::ModelError>& error, |
| std::unique_ptr<syncer::MetadataBatch> metadata_batch); |
| static void OnReadAllData(std::unique_ptr<Builder> builder, |
| const base::Optional<syncer::ModelError>& error); |
| |
| // |sessions_client| must not be null and must outlive this object. |
| SessionStore(const SessionInfo& local_session_info, |
| const RestoredForeignTabCallback& restored_foreign_tab_callback, |
| std::unique_ptr<syncer::ModelTypeStore> underlying_store, |
| std::map<std::string, sync_pb::SessionSpecifics> initial_data, |
| const syncer::EntityMetadataMap& initial_metadata, |
| SyncSessionsClient* sessions_client); |
| |
| const SessionInfo local_session_info_; |
| const RestoredForeignTabCallback restored_foreign_tab_callback_; |
| |
| // In charge of actually persisting changes to disk. |
| const std::unique_ptr<syncer::ModelTypeStore> store_; |
| |
| SyncedSessionTracker session_tracker_; |
| |
| base::WeakPtrFactory<SessionStore> weak_ptr_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(SessionStore); |
| }; |
| |
| } // namespace sync_sessions |
| |
| #endif // COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_ |