1 // Copyright (c) 2012 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 5 #ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 6 #define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "base/compiler_specific.h" 14 #include "base/memory/weak_ptr.h" 15 #include "chrome/browser/sync/glue/data_type_controller.h" 16 #include "chrome/browser/sync/glue/data_type_error_handler.h" 17 #include "chrome/browser/sync/glue/model_associator.h" 18 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" 19 20 class BookmarkModel; 21 class BookmarkNode; 22 class Profile; 23 24 namespace syncer { 25 class BaseNode; 26 class BaseTransaction; 27 struct UserShare; 28 } 29 30 namespace browser_sync { 31 32 // Contains all model association related logic: 33 // * Algorithm to associate bookmark model and sync model. 34 // * Methods to get a bookmark node for a given sync node and vice versa. 35 // * Persisting model associations and loading them back. 36 class BookmarkModelAssociator 37 : public PerDataTypeAssociatorInterface<BookmarkNode, int64> { 38 public: 39 static syncer::ModelType model_type() { return syncer::BOOKMARKS; } 40 // |expect_mobile_bookmarks_folder| controls whether or not we 41 // expect the mobile bookmarks permanent folder to be created. 42 // Should be set to true only by mobile clients. 43 BookmarkModelAssociator( 44 BookmarkModel* bookmark_model, 45 Profile* profile_, 46 syncer::UserShare* user_share, 47 DataTypeErrorHandler* unrecoverable_error_handler, 48 bool expect_mobile_bookmarks_folder); 49 virtual ~BookmarkModelAssociator(); 50 51 // Updates the visibility of the permanents node in the BookmarkModel. 52 void UpdatePermanentNodeVisibility(); 53 54 // AssociatorInterface implementation. 55 // 56 // AssociateModels iterates through both the sync and the browser 57 // bookmark model, looking for matched pairs of items. For any pairs it 58 // finds, it will call AssociateSyncID. For any unmatched items, 59 // MergeAndAssociateModels will try to repair the match, e.g. by adding a new 60 // node. After successful completion, the models should be identical and 61 // corresponding. Returns true on success. On failure of this step, we 62 // should abort the sync operation and report an error to the user. 63 virtual syncer::SyncError AssociateModels( 64 syncer::SyncMergeResult* local_merge_result, 65 syncer::SyncMergeResult* syncer_merge_result) OVERRIDE; 66 67 virtual syncer::SyncError DisassociateModels() OVERRIDE; 68 69 // The has_nodes out param is true if the sync model has nodes other 70 // than the permanent tagged nodes. 71 virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes) OVERRIDE; 72 73 // Returns sync id for the given bookmark node id. 74 // Returns syncer::kInvalidId if the sync node is not found for the given 75 // bookmark node id. 76 virtual int64 GetSyncIdFromChromeId(const int64& node_id) OVERRIDE; 77 78 // Returns the bookmark node for the given sync id. 79 // Returns NULL if no bookmark node is found for the given sync id. 80 virtual const BookmarkNode* GetChromeNodeFromSyncId(int64 sync_id) OVERRIDE; 81 82 // Initializes the given sync node from the given bookmark node id. 83 // Returns false if no sync node was found for the given bookmark node id or 84 // if the initialization of sync node fails. 85 virtual bool InitSyncNodeFromChromeId( 86 const int64& node_id, 87 syncer::BaseNode* sync_node) OVERRIDE; 88 89 // Associates the given bookmark node with the given sync id. 90 virtual void Associate(const BookmarkNode* node, int64 sync_id) OVERRIDE; 91 // Remove the association that corresponds to the given sync id. 92 virtual void Disassociate(int64 sync_id) OVERRIDE; 93 94 virtual void AbortAssociation() OVERRIDE { 95 // No implementation needed, this associator runs on the main 96 // thread. 97 } 98 99 // See ModelAssociator interface. 100 virtual bool CryptoReadyIfNecessary() OVERRIDE; 101 102 protected: 103 // Stores the id of the node with the given tag in |sync_id|. 104 // Returns of that node was found successfully. 105 // Tests override this. 106 virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id); 107 108 private: 109 typedef std::map<int64, int64> BookmarkIdToSyncIdMap; 110 typedef std::map<int64, const BookmarkNode*> SyncIdToBookmarkNodeMap; 111 typedef std::set<int64> DirtyAssociationsSyncIds; 112 113 // Posts a task to persist dirty associations. 114 void PostPersistAssociationsTask(); 115 // Persists all dirty associations. 116 void PersistAssociations(); 117 118 // Matches up the bookmark model and the sync model to build model 119 // associations. 120 syncer::SyncError BuildAssociations( 121 syncer::SyncMergeResult* local_merge_result, 122 syncer::SyncMergeResult* syncer_merge_result); 123 124 // Removes bookmark nodes whose corresponding sync nodes have been deleted 125 // according to sync delete journals. Return number of deleted bookmarks. 126 int64 ApplyDeletesFromSyncJournal(syncer::BaseTransaction* trans); 127 128 // Associate a top-level node of the bookmark model with a permanent node in 129 // the sync domain. Such permanent nodes are identified by a tag that is 130 // well known to the server and the client, and is unique within a particular 131 // user's share. For example, "other_bookmarks" is the tag for the Other 132 // Bookmarks folder. The sync nodes are server-created. 133 // Returns true on success, false if association failed. 134 bool AssociateTaggedPermanentNode( 135 const BookmarkNode* permanent_node, 136 const std::string& tag) WARN_UNUSED_RESULT; 137 138 // Compare the properties of a pair of nodes from either domain. 139 bool NodesMatch(const BookmarkNode* bookmark, 140 const syncer::BaseNode* sync_node) const; 141 142 // Check whether bookmark model and sync model are synced by comparing 143 // their transaction versions. 144 // Returns a PERSISTENCE_ERROR if a transaction mismatch was detected where 145 // the native model has a newer transaction verison. 146 syncer::SyncError CheckModelSyncState( 147 syncer::SyncMergeResult* local_merge_result, 148 syncer::SyncMergeResult* syncer_merge_result) const; 149 150 BookmarkModel* bookmark_model_; 151 Profile* profile_; 152 syncer::UserShare* user_share_; 153 DataTypeErrorHandler* unrecoverable_error_handler_; 154 const bool expect_mobile_bookmarks_folder_; 155 BookmarkIdToSyncIdMap id_map_; 156 SyncIdToBookmarkNodeMap id_map_inverse_; 157 // Stores sync ids for dirty associations. 158 DirtyAssociationsSyncIds dirty_associations_sync_ids_; 159 160 // Used to post PersistAssociation tasks to the current message loop and 161 // guarantees no invocations can occur if |this| has been deleted. (This 162 // allows this class to be non-refcounted). 163 base::WeakPtrFactory<BookmarkModelAssociator> weak_factory_; 164 165 DISALLOW_COPY_AND_ASSIGN(BookmarkModelAssociator); 166 }; 167 168 } // namespace browser_sync 169 170 #endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 171