summaryrefslogtreecommitdiff
path: root/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h
blob: 94b7d51d046c0808b07fc4eaa789165c66556fdb (plain)
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
// 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_BOOKMARKS_BOOKMARK_REMOTE_UPDATES_HANDLER_H_
#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_REMOTE_UPDATES_HANDLER_H_

#include <map>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "components/sync/engine/commit_and_get_updates_types.h"
#include "components/sync_bookmarks/synced_bookmark_tracker.h"

namespace bookmarks {
class BookmarkModel;
class BookmarkNode;
}  // namespace bookmarks

namespace favicon {
class FaviconService;
}  // namespace favicon

namespace sync_bookmarks {

// Responsible for processing one batch of remote updates received from the sync
// server.
class BookmarkRemoteUpdatesHandler {
 public:
  // |bookmark_model|, |favicon_service| and |bookmark_tracker| must not be null
  // and must outlive this object.
  BookmarkRemoteUpdatesHandler(bookmarks::BookmarkModel* bookmark_model,
                               favicon::FaviconService* favicon_service,
                               SyncedBookmarkTracker* bookmark_tracker);

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

  // Processes the updates received from the sync server in |updates| and
  // updates the |bookmark_model_| and |bookmark_tracker_| accordingly. If
  // |got_new_encryption_requirements| is true, it recommits all tracked
  // entities except those in |updates| which should use the latest encryption
  // key and hence don't need recommitting.
  void Process(const syncer::UpdateResponseDataList& updates,
               bool got_new_encryption_requirements);

  // Public for testing.
  static std::vector<const syncer::UpdateResponseData*>
  ReorderValidUpdatesForTest(const syncer::UpdateResponseDataList* updates);

  static size_t ComputeChildNodeIndexForTest(
      const bookmarks::BookmarkNode* parent,
      const sync_pb::UniquePosition& unique_position,
      const SyncedBookmarkTracker* bookmark_tracker);

 private:
  // Reorders incoming updates such that parent creation is before child
  // creation and child deletion is before parent deletion, and deletions should
  // come last. The returned pointers point to the elements in the original
  // |updates|. In this process, invalid updates are filtered out.
  static std::vector<const syncer::UpdateResponseData*> ReorderValidUpdates(
      const syncer::UpdateResponseDataList* updates);

  // Returns the tracked entity that should be affected by a remote change, or
  // null if there is none (e.g. indicating a remote creation).
  // |should_ignore_update| must not be null and it can be marked as true if the
  // function reports that the update should not be processed further (e.g. it
  // is invalid).
  const SyncedBookmarkTracker::Entity* DetermineLocalTrackedEntityToUpdate(
      const syncer::EntityData& update_entity,
      bool* should_ignore_update);

  // Given a remote update entity, it returns the parent bookmark node of the
  // corresponding node. It returns null if the parent node cannot be found.
  const bookmarks::BookmarkNode* GetParentNode(
      const syncer::EntityData& update_entity) const;

  // Processes a remote creation of a bookmark node.
  // 1. For permanent folders, they are only registered in |bookmark_tracker_|.
  // 2. If the nodes parent cannot be found, the remote creation update is
  //    ignored.
  // 3. Otherwise, a new node is created in the local bookmark model and
  //    registered in |bookmark_tracker_|.
  //
  // Returns the newly tracked entity or null if the creation failed.
  const SyncedBookmarkTracker::Entity* ProcessCreate(
      const syncer::UpdateResponseData& update);

  // Processes a remote update of a bookmark node. |update| must not be a
  // deletion, and the server_id must be already tracked, otherwise, it is a
  // creation that gets handled in ProcessCreate(). |tracked_entity| is
  // the tracked entity for that server_id. It is passed as a dependency instead
  // of performing a lookup inside ProcessUpdate() to avoid wasting CPU
  // cycles for doing another lookup (this code runs on the UI thread).
  void ProcessUpdate(const syncer::UpdateResponseData& update,
                     const SyncedBookmarkTracker::Entity* tracked_entity);

  // Processes a remote delete of a bookmark node. |update_entity| must not be a
  // deletion. |tracked_entity| is the tracked entity for that server_id. It is
  // passed as a dependency instead of performing a lookup inside
  // ProcessDelete() to avoid wasting CPU cycles for doing another lookup
  // (this code runs on the UI thread).
  void ProcessDelete(const syncer::EntityData& update_entity,
                     const SyncedBookmarkTracker::Entity* tracked_entity);

  // Processes a conflict where the bookmark has been changed both locally and
  // remotely. It applies the general policy the server wins except in the case
  // of remote deletions in which local wins. |tracked_entity| is the tracked
  // entity for that server_id. It is passed as a dependency instead of
  // performing a lookup inside ProcessDelete() to avoid wasting CPU cycles for
  // doing another lookup (this code runs on the UI thread). Returns the tracked
  // entity (if any) as a result of resolving the conflict, which is often the
  // same as the input |tracked_entity|, but may also be different, including
  // null (if the conflict led to untracking).
  const SyncedBookmarkTracker::Entity* ProcessConflict(
      const syncer::UpdateResponseData& update,
      const SyncedBookmarkTracker::Entity* tracked_entity) WARN_UNUSED_RESULT;

  // Recursively removes the entities corresponding to |node| and its children
  // from |bookmark_tracker_|.
  void RemoveEntityAndChildrenFromTracker(const bookmarks::BookmarkNode* node);

  // Initiate reupload for the update with |entity_data|. |tracked_entity| must
  // not be nullptr.
  void ReuploadEntityIfNeeded(
      const syncer::EntityData& entity_data,
      const SyncedBookmarkTracker::Entity* tracked_entity);

  const raw_ptr<bookmarks::BookmarkModel> bookmark_model_;
  const raw_ptr<favicon::FaviconService> favicon_service_;
  const raw_ptr<SyncedBookmarkTracker> bookmark_tracker_;
};

}  // namespace sync_bookmarks

#endif  // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_REMOTE_UPDATES_HANDLER_H_