15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/sync_driver/data_type_controller.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/sync_driver/data_type_error_handler.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/sync_driver/model_associator.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/unrecoverable_error_handler.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkModel; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkNode; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Profile; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseNode; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseTransaction; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct UserShare; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains all model association related logic: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Algorithm to associate bookmark model and sync model. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Methods to get a bookmark node for a given sync node and vice versa. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Persisting model associations and loading them back. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkModelAssociator 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public sync_driver::PerDataTypeAssociatorInterface<BookmarkNode, int64> { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static syncer::ModelType model_type() { return syncer::BOOKMARKS; } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |expect_mobile_bookmarks_folder| controls whether or not we 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expect the mobile bookmarks permanent folder to be created. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be set to true only by mobile clients. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelAssociator( 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* bookmark_model, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::UserShare* user_share, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_driver::DataTypeErrorHandler* unrecoverable_error_handler, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool expect_mobile_bookmarks_folder); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BookmarkModelAssociator(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates the visibility of the permanents node in the BookmarkModel. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdatePermanentNodeVisibility(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AssociatorInterface implementation. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AssociateModels iterates through both the sync and the browser 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmark model, looking for matched pairs of items. For any pairs it 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // finds, it will call AssociateSyncID. For any unmatched items, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MergeAndAssociateModels will try to repair the match, e.g. by adding a new 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // node. After successful completion, the models should be identical and 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corresponding. Returns true on success. On failure of this step, we 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should abort the sync operation and report an error to the user. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual syncer::SyncError AssociateModels( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* local_merge_result, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* syncer_merge_result) OVERRIDE; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual syncer::SyncError DisassociateModels() OVERRIDE; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The has_nodes out param is true if the sync model has nodes other 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than the permanent tagged nodes. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes) OVERRIDE; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns sync id for the given bookmark node id. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns syncer::kInvalidId if the sync node is not found for the given 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmark node id. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int64 GetSyncIdFromChromeId(const int64& node_id) OVERRIDE; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the bookmark node for the given sync id. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns NULL if no bookmark node is found for the given sync id. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual const BookmarkNode* GetChromeNodeFromSyncId(int64 sync_id) OVERRIDE; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes the given sync node from the given bookmark node id. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns false if no sync node was found for the given bookmark node id or 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the initialization of sync node fails. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool InitSyncNodeFromChromeId( 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64& node_id, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::BaseNode* sync_node) OVERRIDE; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Associates the given bookmark node with the given sync id. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Associate(const BookmarkNode* node, int64 sync_id) OVERRIDE; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the association that corresponds to the given sync id. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Disassociate(int64 sync_id) OVERRIDE; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AbortAssociation() OVERRIDE { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No implementation needed, this associator runs on the main 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See ModelAssociator interface. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool CryptoReadyIfNecessary() OVERRIDE; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stores the id of the node with the given tag in |sync_id|. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns of that node was found successfully. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tests override this. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int64, int64> BookmarkIdToSyncIdMap; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int64, const BookmarkNode*> SyncIdToBookmarkNodeMap; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<int64> DirtyAssociationsSyncIds; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Posts a task to persist dirty associations. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PostPersistAssociationsTask(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Persists all dirty associations. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PersistAssociations(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Matches up the bookmark model and the sync model to build model 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // associations. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncError BuildAssociations( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* local_merge_result, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* syncer_merge_result); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes bookmark nodes whose corresponding sync nodes have been deleted 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // according to sync delete journals. Return number of deleted bookmarks. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 ApplyDeletesFromSyncJournal(syncer::BaseTransaction* trans); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Associate a top-level node of the bookmark model with a permanent node in 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the sync domain. Such permanent nodes are identified by a tag that is 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // well known to the server and the client, and is unique within a particular 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user's share. For example, "other_bookmarks" is the tag for the Other 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bookmarks folder. The sync nodes are server-created. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success, false if association failed. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AssociateTaggedPermanentNode( 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* permanent_node, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& tag) WARN_UNUSED_RESULT; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compare the properties of a pair of nodes from either domain. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool NodesMatch(const BookmarkNode* bookmark, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncer::BaseNode* sync_node) const; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether bookmark model and sync model are synced by comparing 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their transaction versions. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a PERSISTENCE_ERROR if a transaction mismatch was detected where 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the native model has a newer transaction verison. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncError CheckModelSyncState( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* local_merge_result, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::SyncMergeResult* syncer_merge_result) const; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* bookmark_model_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::UserShare* user_share_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_driver::DataTypeErrorHandler* unrecoverable_error_handler_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool expect_mobile_bookmarks_folder_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkIdToSyncIdMap id_map_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncIdToBookmarkNodeMap id_map_inverse_; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stores sync ids for dirty associations. 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DirtyAssociationsSyncIds dirty_associations_sync_ids_; 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to post PersistAssociation tasks to the current message loop and 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guarantees no invocations can occur if |this| has been deleted. (This 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allows this class to be non-refcounted). 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<BookmarkModelAssociator> weak_factory_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BookmarkModelAssociator); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace browser_sync 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)