summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/glue/bookmark_model_associator.h
blob: 31ade9e95df06a91d57bc1aefa2744bc87ad2911 (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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright (c) 2012 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 CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_
#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_
#pragma once

#include <map>
#include <set>
#include <string>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/data_type_error_handler.h"
#include "chrome/browser/sync/glue/model_associator.h"
#include "sync/util/unrecoverable_error_handler.h"

class BookmarkModel;
class BookmarkNode;

namespace sync_api {
class BaseNode;
struct UserShare;
}

namespace browser_sync {

// Contains all model association related logic:
// * Algorithm to associate bookmark model and sync model.
// * Methods to get a bookmark node for a given sync node and vice versa.
// * Persisting model associations and loading them back.
class BookmarkModelAssociator
    : public PerDataTypeAssociatorInterface<BookmarkNode, int64> {
 public:
  static syncable::ModelType model_type() { return syncable::BOOKMARKS; }
  // |expect_mobile_bookmarks_folder| controls whether or not we
  // expect the mobile bookmarks permanent folder to be created.
  // Should be set to true only by mobile clients.
  BookmarkModelAssociator(
      BookmarkModel* bookmark_model,
      sync_api::UserShare* user_share,
      DataTypeErrorHandler* unrecoverable_error_handler,
      bool expect_mobile_bookmarks_folder);
  virtual ~BookmarkModelAssociator();

  // Updates the visibility of the permanents node in the BookmarkModel.
  void UpdatePermanentNodeVisibility();

  // AssociatorInterface implementation.
  //
  // AssociateModels iterates through both the sync and the browser
  // bookmark model, looking for matched pairs of items.  For any pairs it
  // finds, it will call AssociateSyncID.  For any unmatched items,
  // MergeAndAssociateModels will try to repair the match, e.g. by adding a new
  // node.  After successful completion, the models should be identical and
  // corresponding. Returns true on success.  On failure of this step, we
  // should abort the sync operation and report an error to the user.
  virtual SyncError AssociateModels() OVERRIDE;

  virtual SyncError DisassociateModels() OVERRIDE;

  // The has_nodes out param is true if the sync model has nodes other
  // than the permanent tagged nodes.
  virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes) OVERRIDE;

  // Returns sync id for the given bookmark node id.
  // Returns sync_api::kInvalidId if the sync node is not found for the given
  // bookmark node id.
  virtual int64 GetSyncIdFromChromeId(const int64& node_id) OVERRIDE;

  // Returns the bookmark node for the given sync id.
  // Returns NULL if no bookmark node is found for the given sync id.
  virtual const BookmarkNode* GetChromeNodeFromSyncId(int64 sync_id) OVERRIDE;

  // Initializes the given sync node from the given bookmark node id.
  // Returns false if no sync node was found for the given bookmark node id or
  // if the initialization of sync node fails.
  virtual bool InitSyncNodeFromChromeId(
      const int64& node_id,
      sync_api::BaseNode* sync_node) OVERRIDE;

  // Associates the given bookmark node with the given sync id.
  virtual void Associate(const BookmarkNode* node, int64 sync_id) OVERRIDE;
  // Remove the association that corresponds to the given sync id.
  virtual void Disassociate(int64 sync_id) OVERRIDE;

  virtual void AbortAssociation() OVERRIDE {
    // No implementation needed, this associator runs on the main
    // thread.
  }

  // See ModelAssociator interface.
  virtual bool CryptoReadyIfNecessary() OVERRIDE;

 protected:
  // Stores the id of the node with the given tag in |sync_id|.
  // Returns of that node was found successfully.
  // Tests override this.
  virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);

 private:
  typedef std::map<int64, int64> BookmarkIdToSyncIdMap;
  typedef std::map<int64, const BookmarkNode*> SyncIdToBookmarkNodeMap;
  typedef std::set<int64> DirtyAssociationsSyncIds;

  // Posts a task to persist dirty associations.
  void PostPersistAssociationsTask();
  // Persists all dirty associations.
  void PersistAssociations();

  // Loads the persisted associations into in-memory maps.
  // If the persisted associations are out-of-date due to some reason, returns
  // false; otherwise returns true.
  bool LoadAssociations();

  // Matches up the bookmark model and the sync model to build model
  // associations.
  SyncError BuildAssociations();

  // Associate a top-level node of the bookmark model with a permanent node in
  // the sync domain.  Such permanent nodes are identified by a tag that is
  // well known to the server and the client, and is unique within a particular
  // user's share.  For example, "other_bookmarks" is the tag for the Other
  // Bookmarks folder.  The sync nodes are server-created.
  SyncError AssociateTaggedPermanentNode(
      const BookmarkNode* permanent_node,
      const std::string& tag) WARN_UNUSED_RESULT;

  // Compare the properties of a pair of nodes from either domain.
  bool NodesMatch(const BookmarkNode* bookmark,
                  const sync_api::BaseNode* sync_node) const;

  BookmarkModel* bookmark_model_;
  sync_api::UserShare* user_share_;
  DataTypeErrorHandler* unrecoverable_error_handler_;
  const bool expect_mobile_bookmarks_folder_;
  BookmarkIdToSyncIdMap id_map_;
  SyncIdToBookmarkNodeMap id_map_inverse_;
  // Stores sync ids for dirty associations.
  DirtyAssociationsSyncIds dirty_associations_sync_ids_;

  // Used to post PersistAssociation tasks to the current message loop and
  // guarantees no invocations can occur if |this| has been deleted. (This
  // allows this class to be non-refcounted).
  base::WeakPtrFactory<BookmarkModelAssociator> weak_factory_;

  int number_of_new_sync_nodes_created_at_association_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkModelAssociator);
};

}  // namespace browser_sync

#endif  // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_