blob: 199c83e86f3cd843e23f2fb31760bc84f9494295 [file] [log] [blame]
// 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_
#include <map>
#include <set>
#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "components/sync_driver/data_type_controller.h"
#include "components/sync_driver/data_type_error_handler.h"
#include "components/sync_driver/model_associator.h"
#include "sync/internal_api/public/util/unrecoverable_error_handler.h"
class BookmarkModel;
class BookmarkNode;
class Profile;
namespace syncer {
class BaseNode;
class BaseTransaction;
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 sync_driver::PerDataTypeAssociatorInterface<BookmarkNode, int64> {
public:
static syncer::ModelType model_type() { return syncer::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,
Profile* profile_,
syncer::UserShare* user_share,
sync_driver::DataTypeErrorHandler* unrecoverable_error_handler,
bool expect_mobile_bookmarks_folder);
~BookmarkModelAssociator() override;
// 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.
syncer::SyncError AssociateModels(
syncer::SyncMergeResult* local_merge_result,
syncer::SyncMergeResult* syncer_merge_result) override;
syncer::SyncError DisassociateModels() override;
// The has_nodes out param is true if the sync model has nodes other
// than the permanent tagged nodes.
bool SyncModelHasUserCreatedNodes(bool* has_nodes) override;
// Returns sync id for the given bookmark node id.
// Returns syncer::kInvalidId if the sync node is not found for the given
// bookmark node id.
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.
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.
bool InitSyncNodeFromChromeId(const int64& node_id,
syncer::BaseNode* sync_node) override;
// Associates the given bookmark node with the given sync id.
void Associate(const BookmarkNode* node, int64 sync_id) override;
// Remove the association that corresponds to the given sync id.
void Disassociate(int64 sync_id) override;
void AbortAssociation() override {
// No implementation needed, this associator runs on the main
// thread.
}
// See ModelAssociator interface.
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();
// Matches up the bookmark model and the sync model to build model
// associations.
syncer::SyncError BuildAssociations(
syncer::SyncMergeResult* local_merge_result,
syncer::SyncMergeResult* syncer_merge_result);
// Removes bookmark nodes whose corresponding sync nodes have been deleted
// according to sync delete journals. Return number of deleted bookmarks.
int64 ApplyDeletesFromSyncJournal(syncer::BaseTransaction* trans);
// 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.
// Returns true on success, false if association failed.
bool 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 syncer::BaseNode* sync_node) const;
// Check whether bookmark model and sync model are synced by comparing
// their transaction versions.
// Returns a PERSISTENCE_ERROR if a transaction mismatch was detected where
// the native model has a newer transaction verison.
syncer::SyncError CheckModelSyncState(
syncer::SyncMergeResult* local_merge_result,
syncer::SyncMergeResult* syncer_merge_result) const;
BookmarkModel* bookmark_model_;
Profile* profile_;
syncer::UserShare* user_share_;
sync_driver::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_;
DISALLOW_COPY_AND_ASSIGN(BookmarkModelAssociator);
};
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_