summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/glue
diff options
context:
space:
mode:
authortim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-17 19:18:53 +0000
committertim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-17 19:18:53 +0000
commit210007c4ad5225b2b5ca56ee3f009167c9705ac0 (patch)
tree80c4f0a2376914ec49cffb964408e1173cffd144 /chrome/browser/sync/glue
parentb3300dc30deee1992729a78bc5c053c7a136d6a7 (diff)
downloadchromium_src-210007c4ad5225b2b5ca56ee3f009167c9705ac0.zip
chromium_src-210007c4ad5225b2b5ca56ee3f009167c9705ac0.tar.gz
chromium_src-210007c4ad5225b2b5ca56ee3f009167c9705ac0.tar.bz2
Generic ModelAssociator based on prototype from earlier CL.
BUG=29831 TEST=ProfileSyncServiceTest Review URL: http://codereview.chromium.org/507039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34857 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/glue')
-rw-r--r--chrome/browser/sync/glue/bookmark_change_processor.cc33
-rw-r--r--chrome/browser/sync/glue/bookmark_change_processor.h11
-rw-r--r--chrome/browser/sync/glue/bookmark_model_associator.cc33
-rw-r--r--chrome/browser/sync/glue/bookmark_model_associator.h17
-rw-r--r--chrome/browser/sync/glue/change_processor.h2
-rw-r--r--chrome/browser/sync/glue/model_associator.h148
6 files changed, 192 insertions, 52 deletions
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/chrome/browser/sync/glue/bookmark_change_processor.cc
index 916669f..a4e2b47 100644
--- a/chrome/browser/sync/glue/bookmark_change_processor.cc
+++ b/chrome/browser/sync/glue/bookmark_change_processor.cc
@@ -35,6 +35,7 @@ void BookmarkChangeProcessor::StopImpl() {
DCHECK(bookmark_model_);
bookmark_model_->RemoveObserver(this);
bookmark_model_ = NULL;
+ model_associator_ = NULL;
}
void BookmarkChangeProcessor::UpdateSyncNodeProperties(
@@ -68,7 +69,7 @@ void BookmarkChangeProcessor::EncodeFavicon(const BookmarkNode* src,
void BookmarkChangeProcessor::RemoveOneSyncNode(
sync_api::WriteTransaction* trans, const BookmarkNode* node) {
sync_api::WriteNode sync_node(trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->id(), &sync_node)) {
+ if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) {
error_handler()->OnUnrecoverableError();
return;
}
@@ -132,7 +133,7 @@ void BookmarkChangeProcessor::BookmarkNodeAdded(BookmarkModel* model,
// Acquire a scoped write lock via a transaction.
sync_api::WriteTransaction trans(share_handle());
- CreateSyncNode(parent, model, index, &trans, model_associator_.get(),
+ CreateSyncNode(parent, model, index, &trans, model_associator_,
error_handler());
}
@@ -187,7 +188,7 @@ void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model,
// Lookup the sync node that's associated with |node|.
sync_api::WriteNode sync_node(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->id(), &sync_node)) {
+ if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) {
error_handler()->OnUnrecoverableError();
return;
}
@@ -195,7 +196,7 @@ void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model,
UpdateSyncNodeProperties(node, model, &sync_node);
DCHECK_EQ(sync_node.GetIsFolder(), node->is_folder());
- DCHECK_EQ(model_associator_->GetBookmarkNodeFromSyncId(
+ DCHECK_EQ(model_associator_->GetChromeNodeFromSyncId(
sync_node.GetParentId()),
node->GetParent());
// This node's index should be one more than the predecessor's index.
@@ -221,13 +222,13 @@ void BookmarkChangeProcessor::BookmarkNodeMoved(BookmarkModel* model,
// Lookup the sync node that's associated with |child|.
sync_api::WriteNode sync_node(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(child->id(), &sync_node)) {
+ if (!model_associator_->InitSyncNodeFromChromeId(child->id(), &sync_node)) {
error_handler()->OnUnrecoverableError();
return;
}
if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node,
- model_associator_.get(), error_handler())) {
+ model_associator_, error_handler())) {
error_handler()->OnUnrecoverableError();
return;
}
@@ -249,16 +250,16 @@ void BookmarkChangeProcessor::BookmarkNodeChildrenReordered(
// children of the corresponding sync node.
for (int i = 0; i < node->GetChildCount(); ++i) {
sync_api::WriteNode sync_child(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->GetChild(i)->id(),
- &sync_child)) {
+ if (!model_associator_->InitSyncNodeFromChromeId(node->GetChild(i)->id(),
+ &sync_child)) {
error_handler()->OnUnrecoverableError();
return;
}
DCHECK_EQ(sync_child.GetParentId(),
- model_associator_->GetSyncIdFromBookmarkId(node->id()));
+ model_associator_->GetSyncIdFromChromeId(node->id()));
if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child,
- model_associator_.get(), error_handler())) {
+ model_associator_, error_handler())) {
error_handler()->OnUnrecoverableError();
return;
}
@@ -271,7 +272,7 @@ bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation,
sync_api::WriteNode* dst, BookmarkModelAssociator* associator,
UnrecoverableErrorHandler* error_handler) {
sync_api::ReadNode sync_parent(trans);
- if (!associator->InitSyncNodeFromBookmarkId(parent->id(), &sync_parent)) {
+ if (!associator->InitSyncNodeFromChromeId(parent->id(), &sync_parent)) {
LOG(WARNING) << "Parent lookup failed";
error_handler->OnUnrecoverableError();
return false;
@@ -291,7 +292,7 @@ bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation,
// Find the bookmark model predecessor, and insert after it.
const BookmarkNode* prev = parent->GetChild(index - 1);
sync_api::ReadNode sync_prev(trans);
- if (!associator->InitSyncNodeFromBookmarkId(prev->id(), &sync_prev)) {
+ if (!associator->InitSyncNodeFromChromeId(prev->id(), &sync_prev)) {
LOG(WARNING) << "Predecessor lookup failed";
return false;
}
@@ -324,7 +325,7 @@ int BookmarkChangeProcessor::CalculateBookmarkModelInsertionIndex(
// Otherwise, insert after the predecessor bookmark node.
const BookmarkNode* predecessor =
- model_associator_->GetBookmarkNodeFromSyncId(predecessor_id);
+ model_associator_->GetChromeNodeFromSyncId(predecessor_id);
DCHECK(predecessor);
DCHECK_EQ(predecessor->GetParent(), parent);
return parent->IndexOfChild(predecessor) + 1;
@@ -367,7 +368,7 @@ void BookmarkChangeProcessor::ApplyChangesFromSyncModel(
const BookmarkNode* foster_parent = NULL;
for (int i = 0; i < change_count; ++i) {
const BookmarkNode* dst =
- model_associator_->GetBookmarkNodeFromSyncId(changes[i].id);
+ model_associator_->GetChromeNodeFromSyncId(changes[i].id);
// Ignore changes to the permanent top-level nodes. We only care about
// their children.
if ((dst == model->GetBookmarkBarNode()) || (dst == model->other_node()))
@@ -429,7 +430,7 @@ const BookmarkNode* BookmarkChangeProcessor::CreateOrUpdateBookmarkNode(
sync_api::BaseNode* src,
BookmarkModel* model) {
const BookmarkNode* parent =
- model_associator_->GetBookmarkNodeFromSyncId(src->GetParentId());
+ model_associator_->GetChromeNodeFromSyncId(src->GetParentId());
if (!parent) {
DLOG(WARNING) << "Could not find parent of node being added/updated."
<< " Node title: " << src->GetTitle()
@@ -437,7 +438,7 @@ const BookmarkNode* BookmarkChangeProcessor::CreateOrUpdateBookmarkNode(
return NULL;
}
int index = CalculateBookmarkModelInsertionIndex(parent, src);
- const BookmarkNode* dst = model_associator_->GetBookmarkNodeFromSyncId(
+ const BookmarkNode* dst = model_associator_->GetChromeNodeFromSyncId(
src->GetId());
if (!dst) {
dst = CreateBookmarkNode(src, parent, model, index);
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.h b/chrome/browser/sync/glue/bookmark_change_processor.h
index 496b85f..0847919 100644
--- a/chrome/browser/sync/glue/bookmark_change_processor.h
+++ b/chrome/browser/sync/glue/bookmark_change_processor.h
@@ -23,16 +23,13 @@ namespace browser_sync {
// All operations and use of this class are from the UI thread.
// This is currently bookmarks specific.
class BookmarkChangeProcessor : public BookmarkModelObserver,
- public ChangeProcessor {
+ public ChangeProcessor {
public:
explicit BookmarkChangeProcessor(UnrecoverableErrorHandler* error_handler);
virtual ~BookmarkChangeProcessor() {}
void set_model_associator(BookmarkModelAssociator* model_associator) {
- model_associator_.reset(model_associator);
- }
- virtual ModelAssociator* GetModelAssociator() {
- return model_associator_.get();
+ model_associator_ = model_associator;
}
// BookmarkModelObserver implementation.
@@ -162,7 +159,9 @@ class BookmarkChangeProcessor : public BookmarkModelObserver,
// The bookmark model we are processing changes from. Non-NULL when
// |running_| is true.
BookmarkModel* bookmark_model_;
- scoped_ptr<BookmarkModelAssociator> model_associator_;
+
+ // The two models should be associated according to this ModelAssociator.
+ BookmarkModelAssociator* model_associator_;
DISALLOW_COPY_AND_ASSIGN(BookmarkChangeProcessor);
};
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
index 7e220bf..d6ad0ab 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -165,22 +165,22 @@ bool BookmarkModelAssociator::DisassociateModels() {
return true;
}
-int64 BookmarkModelAssociator::GetSyncIdFromBookmarkId(int64 node_id) const {
+int64 BookmarkModelAssociator::GetSyncIdFromChromeId(int64 node_id) {
BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id);
return iter == id_map_.end() ? sync_api::kInvalidId : iter->second;
}
-const BookmarkNode* BookmarkModelAssociator::GetBookmarkNodeFromSyncId(
+const BookmarkNode* BookmarkModelAssociator::GetChromeNodeFromSyncId(
int64 sync_id) {
SyncIdToBookmarkNodeMap::const_iterator iter = id_map_inverse_.find(sync_id);
return iter == id_map_inverse_.end() ? NULL : iter->second;
}
-bool BookmarkModelAssociator::InitSyncNodeFromBookmarkId(
+bool BookmarkModelAssociator::InitSyncNodeFromChromeId(
int64 node_id,
sync_api::BaseNode* sync_node) {
DCHECK(sync_node);
- int64 sync_id = GetSyncIdFromBookmarkId(node_id);
+ int64 sync_id = GetSyncIdFromChromeId(node_id);
if (sync_id == sync_api::kInvalidId)
return false;
if (!sync_node->InitByIdLookup(sync_id))
@@ -251,8 +251,7 @@ bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes() {
}
bool BookmarkModelAssociator::NodesMatch(const BookmarkNode* bookmark,
- const sync_api::BaseNode* sync_node)
- const {
+ const sync_api::BaseNode* sync_node) const {
if (bookmark->GetTitle() != sync_node->GetTitle())
return false;
if (bookmark->is_folder() != sync_node->GetIsFolder())
@@ -270,7 +269,7 @@ bool BookmarkModelAssociator::NodesMatch(const BookmarkNode* bookmark,
bool BookmarkModelAssociator::AssociateTaggedPermanentNode(
const BookmarkNode* permanent_node, const std::string&tag) {
// Do nothing if |permanent_node| is already initialized and associated.
- int64 sync_id = GetSyncIdFromBookmarkId(permanent_node->id());
+ int64 sync_id = GetSyncIdFromChromeId(permanent_node->id());
if (sync_id != sync_api::kInvalidId)
return true;
if (!GetSyncIdForTaggedNode(tag, &sync_id))
@@ -281,7 +280,7 @@ bool BookmarkModelAssociator::AssociateTaggedPermanentNode(
}
bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
- int64* sync_id) {
+ int64* sync_id) {
sync_api::ReadTransaction trans(
sync_service_->backend()->GetUserShareHandle());
sync_api::ReadNode sync_node(&trans);
@@ -340,10 +339,10 @@ bool BookmarkModelAssociator::BuildAssociations() {
<< "are running against an out-of-date server?";
return false;
}
- int64 bookmark_bar_sync_id = GetSyncIdFromBookmarkId(
+ int64 bookmark_bar_sync_id = GetSyncIdFromChromeId(
model->GetBookmarkBarNode()->id());
DCHECK(bookmark_bar_sync_id != sync_api::kInvalidId);
- int64 other_bookmarks_sync_id = GetSyncIdFromBookmarkId(
+ int64 other_bookmarks_sync_id = GetSyncIdFromChromeId(
model->other_node()->id());
DCHECK(other_bookmarks_sync_id != sync_api::kInvalidId);
@@ -366,7 +365,7 @@ bool BookmarkModelAssociator::BuildAssociations() {
// Only folder nodes are pushed on to the stack.
DCHECK(sync_parent.GetIsFolder());
- const BookmarkNode* parent_node = GetBookmarkNodeFromSyncId(sync_parent_id);
+ const BookmarkNode* parent_node = GetChromeNodeFromSyncId(sync_parent_id);
DCHECK(parent_node->is_folder());
BookmarkNodeFinder node_finder(parent_node);
@@ -385,10 +384,10 @@ bool BookmarkModelAssociator::BuildAssociations() {
if (child_node) {
model->Move(child_node, parent_node, index);
// Set the favicon for bookmark node from sync node or vice versa.
- if (BookmarkChangeProcessor::SetBookmarkFavicon(&sync_child_node,
- child_node, sync_service_->profile())) {
+ if (BookmarkChangeProcessor::SetBookmarkFavicon(
+ &sync_child_node, child_node, sync_service_->profile())) {
BookmarkChangeProcessor::SetSyncNodeFavicon(child_node, model,
- &sync_child_node);
+ &sync_child_node);
}
} else {
// Create a new bookmark node for the sync node.
@@ -409,8 +408,8 @@ bool BookmarkModelAssociator::BuildAssociations() {
// So the children starting from index in the parent bookmark node are the
// ones that are not present in the parent sync node. So create them.
for (int i = index; i < parent_node->GetChildCount(); ++i) {
- sync_child_id = BookmarkChangeProcessor::CreateSyncNode(parent_node,
- model, i, &trans, this, sync_service_);
+ sync_child_id = BookmarkChangeProcessor::CreateSyncNode(
+ parent_node, model, i, &trans, this, sync_service_);
if (parent_node->GetChild(i)->is_folder())
dfs_stack.push(sync_child_id);
}
@@ -450,7 +449,7 @@ void BookmarkModelAssociator::PersistAssociations() {
sync_service_->OnUnrecoverableError();
return;
}
- const BookmarkNode* node = GetBookmarkNodeFromSyncId(sync_id);
+ const BookmarkNode* node = GetChromeNodeFromSyncId(sync_id);
if (node)
sync_node.SetExternalId(node->id());
else
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.h b/chrome/browser/sync/glue/bookmark_model_associator.h
index d722367..0a4fcb97 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.h
+++ b/chrome/browser/sync/glue/bookmark_model_associator.h
@@ -31,11 +31,15 @@ class BookmarkChangeProcessor;
// * 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 ModelAssociator {
+class BookmarkModelAssociator
+ : public PerDataTypeAssociatorInterface<BookmarkNode, int64> {
public:
+ static const ModelType model_type() { return MODEL_TYPE_BOOKMARKS; }
explicit BookmarkModelAssociator(ProfileSyncService* sync_service);
virtual ~BookmarkModelAssociator() { }
+ // 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,
@@ -60,21 +64,22 @@ class BookmarkModelAssociator : public ModelAssociator {
// 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.
- int64 GetSyncIdFromBookmarkId(int64 node_id) const;
+ virtual int64 GetSyncIdFromChromeId(int64 node_id);
// Returns the bookmark node for the given sync id.
// Returns NULL if no bookmark node is found for the given sync id.
- const BookmarkNode* GetBookmarkNodeFromSyncId(int64 sync_id);
+ virtual const BookmarkNode* GetChromeNodeFromSyncId(int64 sync_id);
// 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 InitSyncNodeFromBookmarkId(int64 node_id, sync_api::BaseNode* sync_node);
+ virtual bool InitSyncNodeFromChromeId(int64 node_id,
+ sync_api::BaseNode* sync_node);
// Associates the given bookmark node with the given sync id.
- void Associate(const BookmarkNode* node, int64 sync_id);
+ virtual void Associate(const BookmarkNode* node, int64 sync_id);
// Remove the association that corresponds to the given sync id.
- void Disassociate(int64 sync_id);
+ virtual void Disassociate(int64 sync_id);
protected:
// Stores the id of the node with the given tag in |sync_id|.
diff --git a/chrome/browser/sync/glue/change_processor.h b/chrome/browser/sync/glue/change_processor.h
index 2537636..21052a7 100644
--- a/chrome/browser/sync/glue/change_processor.h
+++ b/chrome/browser/sync/glue/change_processor.h
@@ -35,8 +35,6 @@ class ChangeProcessor {
void Stop();
bool IsRunning() const { return running_; }
- virtual ModelAssociator* GetModelAssociator() = 0;
-
// Changes have been applied to the backend model and are ready to be
// applied to the frontend model. See syncapi.h for detailed instructions on
// how to interpret and process |changes|.
diff --git a/chrome/browser/sync/glue/model_associator.h b/chrome/browser/sync/glue/model_associator.h
index 7e09be2..43de828 100644
--- a/chrome/browser/sync/glue/model_associator.h
+++ b/chrome/browser/sync/glue/model_associator.h
@@ -5,15 +5,35 @@
#ifndef CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATOR_H_
#define CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATOR_H_
-#include "chrome/browser/sync/engine/syncapi.h"
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+
+namespace sync_api {
+class BaseNode;
+class BaseTransaction;
+class ReadNode;
+}
+
+class ProfileSyncService;
namespace browser_sync {
-// Contains all model association related logic to associate the chrome model
-// with the sync model.
-class ModelAssociator {
+// An enum identifying the various types of browser object models we know how
+// to "associate" with the sync engine view of the world.
+enum ModelType {
+ MODEL_TYPE_BOOKMARKS,
+};
+
+// This represents the fundamental operations used for model association that
+// are common to all ModelAssociators and do not depend on types of the models
+// being associated.
+class AssociatorInterface {
public:
- virtual ~ModelAssociator() {}
+ virtual ~AssociatorInterface() {}
// Iterates through both the sync and the chrome model looking for matched
// pairs of items. After successful completion, the models should be identical
@@ -32,6 +52,124 @@ class ModelAssociator {
virtual bool ChromeModelHasUserCreatedNodes() = 0;
};
+// In addition to the generic methods, association can refer to operations
+// that depend on the types of the actual IDs we are associating and the
+// underlying node type in the browser. We collect these into a templatized
+// interface that encapsulates everything you need to implement to have a model
+// associator for a specific data type.
+// This template is appropriate for data types where a Node* makes sense for
+// referring to a particular item. If we encounter a type that does not fit
+// in this world, we may want to have several PerDataType templates.
+template <class Node, class IDType>
+class PerDataTypeAssociatorInterface : public AssociatorInterface {
+ public:
+ virtual ~PerDataTypeAssociatorInterface() {}
+ // Returns sync id for the given chrome model id.
+ // Returns sync_api::kInvalidId if the sync node is not found for the given
+ // chrome id.
+ virtual int64 GetSyncIdFromChromeId(IDType id) = 0;
+
+ // Returns the chrome node for the given sync id.
+ // Returns NULL if no node is found for the given sync id.
+ virtual const Node* GetChromeNodeFromSyncId(int64 sync_id) = 0;
+
+ // Initializes the given sync node from the given chrome node id.
+ // Returns false if no sync node was found for the given chrome node id or
+ // if the initialization of sync node fails.
+ virtual bool InitSyncNodeFromChromeId(IDType node_id,
+ sync_api::BaseNode* sync_node) = 0;
+
+ // Associates the given chrome node with the given sync id.
+ virtual void Associate(const Node* node, int64 sync_id) = 0;
+
+ // Remove the association that corresponds to the given sync id.
+ virtual void Disassociate(int64 sync_id) = 0;
+};
+
+// Contains all model association related logic to associate the chrome model
+// with the sync model.
+class ModelAssociator : public AssociatorInterface {
+ public:
+ explicit ModelAssociator(ProfileSyncService* sync_service)
+ : sync_service_(sync_service) {
+ DCHECK(sync_service);
+ }
+ ~ModelAssociator() { CleanupAllAssociators(); }
+
+ // AssociatorInterface implementation. These are aggregated across all known
+ // data types (for example, if both a Bookmarks and Preferences association
+ // implementation is registered, AssociateModels() will associate both
+ // Bookmarks and Preferences with the sync model).
+ virtual bool AssociateModels() {
+ bool success = true;
+ for (ImplMap::iterator i = impl_map_.begin(); i != impl_map_.end(); ++i)
+ success &= i->second->AssociateModels();
+ return success;
+ }
+
+ virtual bool DisassociateModels() {
+ bool success = true;
+ for (ImplMap::iterator i = impl_map_.begin(); i != impl_map_.end(); ++i)
+ success &= i->second->DisassociateModels();
+ return success;
+ }
+
+ virtual bool SyncModelHasUserCreatedNodes() {
+ for (ImplMap::iterator i = impl_map_.begin(); i != impl_map_.end(); ++i) {
+ if (i->second->SyncModelHasUserCreatedNodes())
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool ChromeModelHasUserCreatedNodes() {
+ for (ImplMap::iterator i = impl_map_.begin(); i != impl_map_.end(); ++i) {
+ if (i->second->ChromeModelHasUserCreatedNodes())
+ return true;
+ }
+ return false;
+ }
+
+ // Call to enable model association for a particular data type by registering
+ // a type specific association implementation. This will unregister any
+ // previous implementation for the same model type, to enforce only one impl
+ // for a given type at a time.
+ template <class Impl>
+ void CreateAndRegisterPerDataTypeImpl() {
+ UnregisterPerDataTypeImpl<Impl>();
+ impl_map_[Impl::model_type()] = new Impl(sync_service_);
+ }
+
+ // Call to disable model association for a particular data type by
+ // unregistering the specific association implementation.
+ template <class Impl>
+ void UnregisterPerDataTypeImpl() {
+ ImplMap::iterator it = impl_map_.find(Impl::model_type());
+ if (it == impl_map_.end())
+ return;
+ delete it->second;
+ impl_map_.erase(it);
+ }
+
+ template <class Impl>
+ Impl* GetImpl() {
+ ImplMap::const_iterator it = impl_map_.find(Impl::model_type());
+ // The cast is safe because of the static model_type() pattern.
+ return reinterpret_cast<Impl*>(it->second);
+ }
+
+ void CleanupAllAssociators() {
+ STLDeleteValues(&impl_map_);
+ }
+
+ private:
+ ProfileSyncService* sync_service_;
+
+ typedef std::map<ModelType, AssociatorInterface*> ImplMap;
+ ImplMap impl_map_;
+ DISALLOW_COPY_AND_ASSIGN(ModelAssociator);
+};
+
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATOR_H_