// 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 #include #include #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 { 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 BookmarkIdToSyncIdMap; typedef std::map SyncIdToBookmarkNodeMap; typedef std::set 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 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_