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)