synced_bookmark_tracker.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // 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. #ifndef COMPONENTS_SYNC_BOOKMARKS_SYNCED_BOOKMARK_TRACKER_H_
  5. #define COMPONENTS_SYNC_BOOKMARKS_SYNCED_BOOKMARK_TRACKER_H_
  6. #include <memory>
  7. #include <string>
  8. #include <unordered_map>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/time/time.h"
  13. #include "components/sync/base/client_tag_hash.h"
  14. #include "components/sync/protocol/model_type_state.pb.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. namespace sync_pb {
  17. class BookmarkModelMetadata;
  18. class EntitySpecifics;
  19. } // namespace sync_pb
  20. namespace base {
  21. class GUID;
  22. } // namespace base
  23. namespace bookmarks {
  24. class BookmarkModel;
  25. class BookmarkNode;
  26. } // namespace bookmarks
  27. namespace sync_bookmarks {
  28. class SyncedBookmarkTrackerEntity;
  29. // This class is responsible for keeping the mapping between bookmark nodes in
  30. // the local model and the server-side corresponding sync entities. It manages
  31. // the metadata for its entities and caches entity data upon a local change
  32. // until commit confirmation is received.
  33. class SyncedBookmarkTracker {
  34. public:
  35. // Returns a client tag hash given a bookmark GUID.
  36. static syncer::ClientTagHash GetClientTagHashFromGUID(const base::GUID& guid);
  37. // Creates an empty instance with no entities. Never returns null.
  38. static std::unique_ptr<SyncedBookmarkTracker> CreateEmpty(
  39. sync_pb::ModelTypeState model_type_state);
  40. // Loads a tracker from a proto (usually from disk) after enforcing the
  41. // consistency of the metadata against the BookmarkModel. Returns null if the
  42. // data is inconsistent with sync metadata (i.e. corrupt). |model| must not be
  43. // null.
  44. static std::unique_ptr<SyncedBookmarkTracker>
  45. CreateFromBookmarkModelAndMetadata(
  46. const bookmarks::BookmarkModel* model,
  47. sync_pb::BookmarkModelMetadata model_metadata);
  48. SyncedBookmarkTracker(const SyncedBookmarkTracker&) = delete;
  49. SyncedBookmarkTracker& operator=(const SyncedBookmarkTracker&) = delete;
  50. ~SyncedBookmarkTracker();
  51. // This method is used to denote that all bookmarks are reuploaded and there
  52. // is no need to reupload them again after next browser startup.
  53. void SetBookmarksReuploaded();
  54. // Returns null if no entity is found.
  55. const SyncedBookmarkTrackerEntity* GetEntityForSyncId(
  56. const std::string& sync_id) const;
  57. // Returns null if no entity is found.
  58. const SyncedBookmarkTrackerEntity* GetEntityForClientTagHash(
  59. const syncer::ClientTagHash& client_tag_hash) const;
  60. // Convenience function, similar to GetEntityForClientTagHash().
  61. const SyncedBookmarkTrackerEntity* GetEntityForGUID(
  62. const base::GUID& guid) const;
  63. // Returns null if no entity is found.
  64. const SyncedBookmarkTrackerEntity* GetEntityForBookmarkNode(
  65. const bookmarks::BookmarkNode* node) const;
  66. // Starts tracking local bookmark |bookmark_node|, which must not be tracked
  67. // beforehand. The rest of the arguments represent the initial metadata.
  68. // Returns the tracked entity.
  69. const SyncedBookmarkTrackerEntity* Add(
  70. const bookmarks::BookmarkNode* bookmark_node,
  71. const std::string& sync_id,
  72. int64_t server_version,
  73. base::Time creation_time,
  74. const sync_pb::EntitySpecifics& specifics);
  75. // Updates the sync metadata for a tracked entity. |entity| must be owned by
  76. // this tracker.
  77. void Update(const SyncedBookmarkTrackerEntity* entity,
  78. int64_t server_version,
  79. base::Time modification_time,
  80. const sync_pb::EntitySpecifics& specifics);
  81. // Updates the server version of an existing entity. |entity| must be owned by
  82. // this tracker.
  83. void UpdateServerVersion(const SyncedBookmarkTrackerEntity* entity,
  84. int64_t server_version);
  85. // Marks an existing entry that a commit request might have been sent to the
  86. // server. |entity| must be owned by this tracker.
  87. void MarkCommitMayHaveStarted(const SyncedBookmarkTrackerEntity* entity);
  88. // This class maintains the order of calls to this method and the same order
  89. // is guaranteed when returning local changes in
  90. // GetEntitiesWithLocalChanges() as well as in BuildBookmarkModelMetadata().
  91. // |entity| must be owned by this tracker.
  92. void MarkDeleted(const SyncedBookmarkTrackerEntity* entity);
  93. // Untracks an entity, which also invalidates the pointer. |entity| must be
  94. // owned by this tracker.
  95. void Remove(const SyncedBookmarkTrackerEntity* entity);
  96. // Increment sequence number in the metadata for |entity|. |entity| must be
  97. // owned by this tracker.
  98. void IncrementSequenceNumber(const SyncedBookmarkTrackerEntity* entity);
  99. sync_pb::BookmarkModelMetadata BuildBookmarkModelMetadata() const;
  100. // Returns true if there are any local entities to be committed.
  101. bool HasLocalChanges() const;
  102. const sync_pb::ModelTypeState& model_type_state() const {
  103. return model_type_state_;
  104. }
  105. void set_model_type_state(sync_pb::ModelTypeState model_type_state) {
  106. model_type_state_ = std::move(model_type_state);
  107. }
  108. std::vector<const SyncedBookmarkTrackerEntity*> GetAllEntities() const;
  109. std::vector<const SyncedBookmarkTrackerEntity*> GetEntitiesWithLocalChanges()
  110. const;
  111. // Updates the tracker after receiving the commit response. |sync_id| should
  112. // match the already tracked sync ID for |entity|, with the exception of the
  113. // initial commit, where the temporary client-generated ID will be overridden
  114. // by the server-provided final ID. |entity| must be owned by this tracker.
  115. void UpdateUponCommitResponse(const SyncedBookmarkTrackerEntity* entity,
  116. const std::string& sync_id,
  117. int64_t server_version,
  118. int64_t acked_sequence_number);
  119. // Informs the tracker that the sync ID for |entity| has changed. It updates
  120. // the internal state of the tracker accordingly. |entity| must be owned by
  121. // this tracker.
  122. void UpdateSyncIdIfNeeded(const SyncedBookmarkTrackerEntity* entity,
  123. const std::string& sync_id);
  124. // Used to start tracking an entity that overwrites a previous local tombstone
  125. // (e.g. user-initiated bookmark deletion undo). |entity| must be owned by
  126. // this tracker.
  127. void UndeleteTombstoneForBookmarkNode(
  128. const SyncedBookmarkTrackerEntity* entity,
  129. const bookmarks::BookmarkNode* node);
  130. // Set the value of |EntityMetadata.acked_sequence_number| for |entity| to be
  131. // equal to |EntityMetadata.sequence_number| such that it is not returned in
  132. // GetEntitiesWithLocalChanges(). |entity| must be owned by this tracker.
  133. void AckSequenceNumber(const SyncedBookmarkTrackerEntity* entity);
  134. // Whether the tracker is empty or not.
  135. bool IsEmpty() const;
  136. // Returns the estimate of dynamically allocated memory in bytes.
  137. size_t EstimateMemoryUsage() const;
  138. // Returns number of tracked bookmarks that aren't deleted.
  139. size_t TrackedBookmarksCount() const;
  140. // Returns number of bookmarks that have been deleted but the server hasn't
  141. // confirmed the deletion yet.
  142. size_t TrackedUncommittedTombstonesCount() const;
  143. // Returns number of tracked entities. Used only in test.
  144. size_t TrackedEntitiesCountForTest() const;
  145. // Clears the specifics hash for |entity|, useful for testing.
  146. void ClearSpecificsHashForTest(const SyncedBookmarkTrackerEntity* entity);
  147. // Checks whther all nodes in |bookmark_model| that *should* be tracked as per
  148. // CanSyncNode() are tracked.
  149. void CheckAllNodesTracked(
  150. const bookmarks::BookmarkModel* bookmark_model) const;
  151. // This method is used to mark all entities except permanent nodes as
  152. // unsynced. This will cause reuploading of all bookmarks. The reupload
  153. // will be initiated only when the |bookmarks_hierarchy_fields_reuploaded|
  154. // field in BookmarksMetadata is false. This field is used to prevent
  155. // reuploading after each browser restart. Returns true if the reupload was
  156. // initiated.
  157. // TODO(crbug.com/1232951): remove this code when most of bookmarks are
  158. // reuploaded.
  159. bool ReuploadBookmarksOnLoadIfNeeded();
  160. // Causes the tracker to remember that a remote sync update (initial or
  161. // incremental) was ignored because its parent was unknown (either because
  162. // the data was corrupt or because the update is a descendant of an
  163. // unsupported permanent folder).
  164. void RecordIgnoredServerUpdateDueToMissingParent(int64_t server_version);
  165. absl::optional<int64_t> GetNumIgnoredUpdatesDueToMissingParentForTest() const;
  166. absl::optional<int64_t>
  167. GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest() const;
  168. private:
  169. // Enumeration of possible reasons why persisted metadata are considered
  170. // corrupted and don't match the bookmark model. Used in UMA metrics. Do not
  171. // re-order or delete these entries; they are used in a UMA histogram. Please
  172. // edit SyncBookmarkModelMetadataCorruptionReason in enums.xml if a value is
  173. // added.
  174. enum class CorruptionReason {
  175. NO_CORRUPTION = 0,
  176. MISSING_SERVER_ID = 1,
  177. BOOKMARK_ID_IN_TOMBSTONE = 2,
  178. MISSING_BOOKMARK_ID = 3,
  179. // COUNT_MISMATCH = 4, // Deprecated.
  180. // IDS_MISMATCH = 5, // Deprecated.
  181. DUPLICATED_SERVER_ID = 6,
  182. UNKNOWN_BOOKMARK_ID = 7,
  183. UNTRACKED_BOOKMARK = 8,
  184. BOOKMARK_GUID_MISMATCH = 9,
  185. DUPLICATED_CLIENT_TAG_HASH = 10,
  186. TRACKED_MANAGED_NODE = 11,
  187. MISSING_CLIENT_TAG_HASH = 12,
  188. MISSING_FAVICON_HASH = 13,
  189. kMaxValue = MISSING_FAVICON_HASH
  190. };
  191. SyncedBookmarkTracker(
  192. sync_pb::ModelTypeState model_type_state,
  193. bool bookmarks_reuploaded,
  194. absl::optional<int64_t> num_ignored_updates_due_to_missing_parent,
  195. absl::optional<int64_t>
  196. max_version_among_ignored_updates_due_to_missing_parent);
  197. // Add entities to |this| tracker based on the content of |*model| and
  198. // |model_metadata|. Validates the integrity of |*model| and |model_metadata|
  199. // and returns an enum representing any inconsistency.
  200. CorruptionReason InitEntitiesFromModelAndMetadata(
  201. const bookmarks::BookmarkModel* model,
  202. sync_pb::BookmarkModelMetadata model_metadata);
  203. // Conceptually, find a tracked entity that matches |entity| and returns a
  204. // non-const pointer of it. The actual implementation is a const_cast.
  205. // |entity| must be owned by this tracker.
  206. SyncedBookmarkTrackerEntity* AsMutableEntity(
  207. const SyncedBookmarkTrackerEntity* entity);
  208. // Reorders |entities| that represents local non-deletions such that parent
  209. // creation/update is before child creation/update. Returns the ordered list.
  210. std::vector<const SyncedBookmarkTrackerEntity*>
  211. ReorderUnsyncedEntitiesExceptDeletions(
  212. const std::vector<const SyncedBookmarkTrackerEntity*>& entities) const;
  213. // Recursive method that starting from |node| appends all corresponding
  214. // entities with updates in top-down order to |ordered_entities|.
  215. void TraverseAndAppend(
  216. const bookmarks::BookmarkNode* node,
  217. std::vector<const SyncedBookmarkTrackerEntity*>* ordered_entities) const;
  218. // A map of sync server ids to sync entities. This should contain entries and
  219. // metadata for almost everything.
  220. std::unordered_map<std::string, std::unique_ptr<SyncedBookmarkTrackerEntity>>
  221. sync_id_to_entities_map_;
  222. // Index for efficient lookups by client tag hash.
  223. std::unordered_map<syncer::ClientTagHash,
  224. const SyncedBookmarkTrackerEntity*,
  225. syncer::ClientTagHash::Hash>
  226. client_tag_hash_to_entities_map_;
  227. // A map of bookmark nodes to sync entities. It's keyed by the bookmark node
  228. // pointers which get assigned when loading the bookmark model. This map is
  229. // first initialized in the constructor.
  230. std::unordered_map<const bookmarks::BookmarkNode*,
  231. SyncedBookmarkTrackerEntity*>
  232. bookmark_node_to_entities_map_;
  233. // A list of pending local bookmark deletions. They should be sent to the
  234. // server in the same order as stored in the list. The same order should also
  235. // be maintained across browser restarts (i.e. across calls to the ctor() and
  236. // BuildBookmarkModelMetadata().
  237. std::vector<SyncedBookmarkTrackerEntity*> ordered_local_tombstones_;
  238. // The model metadata (progress marker, initial sync done, etc).
  239. sync_pb::ModelTypeState model_type_state_;
  240. // This field contains the value of
  241. // BookmarksMetadata::bookmarks_hierarchy_fields_reuploaded.
  242. // TODO(crbug.com/1232951): remove this code when most of bookmarks are
  243. // reuploaded.
  244. bool bookmarks_reuploaded_ = false;
  245. // See corresponding proto fields in BookmarkModelMetadata.
  246. absl::optional<int64_t> num_ignored_updates_due_to_missing_parent_;
  247. absl::optional<int64_t>
  248. max_version_among_ignored_updates_due_to_missing_parent_;
  249. };
  250. } // namespace sync_bookmarks
  251. #endif // COMPONENTS_SYNC_BOOKMARKS_SYNCED_BOOKMARK_TRACKER_H_