| // Copyright 2026 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_MODEL_PROCESSOR_ENTITY_METADATA_H_ | |
| #define COMPONENTS_SYNC_MODEL_PROCESSOR_ENTITY_METADATA_H_ | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include "base/time/time.h" | |
| #include "components/sync/base/client_tag_hash.h" | |
| #include "components/sync/protocol/entity_metadata.pb.h" | |
| class GURL; | |
| namespace base { | |
| class FilePath; | |
| } // namespace base | |
| namespace sync_pb { | |
| class EntitySpecifics; | |
| class UniquePosition; | |
| } // namespace sync_pb | |
| namespace syncer { | |
| struct EntityData; | |
| class CollaborationMetadata; | |
| struct CommitResponseData; | |
| struct UpdateResponseData; | |
| class DeletionOrigin; | |
| // Class representing the metadata associated to a sync entity tracked | |
| // internally by a processor in-memory. | |
| class ProcessorEntityMetadata { | |
| public: | |
| // Checks if the given `metadata` is valid. | |
| static bool IsValid(const sync_pb::EntityMetadata& metadata); | |
| // Creates a new ProcessorEntityMetadata with default values. | |
| static ProcessorEntityMetadata CreateNew(const ClientTagHash& client_tag_hash, | |
| std::string server_id, | |
| base::Time creation_time); | |
| // Creates a ProcessorEntityMetadata from a proto. Returns null if the proto | |
| // is invalid. | |
| static std::unique_ptr<ProcessorEntityMetadata> FromProto( | |
| sync_pb::EntityMetadata metadata); | |
| ~ProcessorEntityMetadata(); | |
| ProcessorEntityMetadata(const ProcessorEntityMetadata&) = delete; | |
| ProcessorEntityMetadata& operator=(const ProcessorEntityMetadata&) = delete; | |
| ProcessorEntityMetadata(ProcessorEntityMetadata&&) = default; | |
| ProcessorEntityMetadata& operator=(ProcessorEntityMetadata&&) = default; | |
| // Returns the underlying proto metadata. | |
| const sync_pb::EntityMetadata& proto() const { return metadata_; } | |
| // Returns true if the entity is deleted. | |
| bool IsDeleted() const; | |
| // Returns true if the entity has local changes that have not been | |
| // acknowledged by the server yet. | |
| bool IsUnsynced() const; | |
| // Returns true if the entity was created locally and has not been committed | |
| // to the server yet. | |
| bool IsUnsyncedLocalCreation() const; | |
| // Returns true if the server version of this entity is greater than or equal | |
| // to `update_version`. | |
| bool IsVersionAlreadyKnown(int64_t update_version) const; | |
| // Overrides the server ID and version. | |
| void OverrideServerMetadata(const std::string& server_id, | |
| int64_t server_version); | |
| // Returns the estimate of dynamically allocated memory in bytes. | |
| size_t EstimateMemoryUsage() const; | |
| // Returns the client tag hash of the entity. | |
| ClientTagHash GetClientTagHash() const; | |
| // Increments the sequence number of the entity, indicating a local change. | |
| // This will also update the base_specifics_hash if the entity was not already | |
| // unsynced. | |
| // TODO(crbug.com/40823197): Consider replacing IncrementSequenceNumber() with | |
| // a higher-level domain API (e.g. MarkForRecommit()) to avoid exposing | |
| // low-level sequence number counter semantics to callers. | |
| void IncrementSequenceNumber(); | |
| // Returns true if the entity's specifics hash (sync-ed or unsynced) matches | |
| // the specifics in `data`. Also checks that deletion status matches. | |
| bool MatchesData(const EntityData& data) const; | |
| // Returns true if the entity's base specifics hash matches the specifics in | |
| // `data`. Base data represents the last specifics known by both the client | |
| // and server. | |
| bool MatchesBaseData(const EntityData& data) const; | |
| // Returns true if the entity's specifics hash matches its base specifics | |
| // hash. This is true if the entity is in sync or if the local changes did not | |
| // modify the specifics (e.g. only metadata changed). | |
| bool MatchesOwnBaseData() const; | |
| // Returns true if the entity's specifics hash matches the hash of | |
| // `specifics`. The entity must not be deleted. | |
| bool MatchesSpecificsHash(const sync_pb::EntitySpecifics& specifics) const; | |
| // Returns true if `favicon_png_bytes` matches the tracked favicon hash. | |
| // The entity must not be deleted. | |
| bool MatchesFaviconHash(const std::string& favicon_png_bytes) const; | |
| // Records that a remote update was ignored. Updates server_id and | |
| // server_version. | |
| void RecordIgnoredRemoteUpdate(const UpdateResponseData& update); | |
| // Records that a remote update was accepted. Updates all metadata fields. | |
| void RecordAcceptedRemoteUpdate( | |
| const UpdateResponseData& update, | |
| sync_pb::EntitySpecifics trimmed_specifics, | |
| std::optional<sync_pb::UniquePosition> unique_position); | |
| // Records a forced remote update (conflict resolution where server wins). | |
| // Acks all pending commits and accepts the update. | |
| void RecordForcedRemoteUpdate( | |
| const UpdateResponseData& update, | |
| sync_pb::EntitySpecifics trimmed_specifics, | |
| std::optional<sync_pb::UniquePosition> unique_position); | |
| // Records a commit response. | |
| void RecordCommitResponse(const CommitResponseData& data); | |
| // Performs a local update based on the provided `data`, updating metadata | |
| // fields. | |
| void RecordLocalUpdate( | |
| const EntityData& data, | |
| sync_pb::EntitySpecifics trimmed_specifics, | |
| std::optional<sync_pb::UniquePosition> unique_position); | |
| // Performs a local deletion, updating metadata fields. | |
| void RecordLocalDeletion(const DeletionOrigin& origin); | |
| // Returns true if an outgoing attachment upload is queued or in progress and | |
| // has not yet produced a `temporary_blob_id`. | |
| bool HasPendingAttachmentUpload() const; | |
| // Marks that a local attachment upload for `file_path` is queued for this | |
| // entity before the asynchronous upload handshake completes, clearing any | |
| // previous `attachment` or `upload_url`. Does not increment the sequence | |
| // number itself; the entity must already be unsynced (e.g. via an | |
| // accompanying `RecordLocalUpdate()` call). | |
| void RecordAttachmentUploadQueued(const base::FilePath& file_path); | |
| // Records that the asynchronous upload handshake completed and returned the | |
| // resumable session `upload_url`. | |
| void RecordAttachmentUploadResumeUrlReceived(const GURL& upload_url); | |
| // Records that the outgoing attachment upload finished and returned | |
| // `temporary_blob_id`, clearing `pending_upload` from metadata. | |
| void RecordAttachmentUploadCompleted(const std::string& temporary_blob_id); | |
| // Clears `pending_upload` from metadata if an attachment upload is queued or | |
| // in progress. | |
| void RecordPendingAttachmentUploadCleared(); | |
| private: | |
| explicit ProcessorEntityMetadata(sync_pb::EntityMetadata metadata); | |
| // Updates the specifics hash in the metadata based on `specifics`. | |
| void UpdateSpecificsHash(const sync_pb::EntitySpecifics& specifics); | |
| sync_pb::EntityMetadata metadata_; | |
| }; | |
| } // namespace syncer | |
| #endif // COMPONENTS_SYNC_MODEL_PROCESSOR_ENTITY_METADATA_H_ |