Index: chrome/browser/sync/glue/bookmark_model_associator.cc |
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc |
index 69e4a7f091da1a3f2224c248194790d4e62cb89f..ea98f9d3f84790e7d7d890e228655f2644bb61ff 100644 |
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc |
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc |
@@ -66,38 +66,6 @@ const char kOtherBookmarksTag[] = "other_bookmarks"; |
// limits; see write_node.cc). |
const int kTitleLimitBytes = 255; |
-// Bookmark comparer for map of bookmark nodes. |
-class BookmarkComparer { |
- public: |
- // Compares the two given nodes and returns whether node1 should appear |
- // before node2 in strict weak ordering. |
- bool operator()(const BookmarkNode* node1, |
- const BookmarkNode* node2) const { |
- DCHECK(node1); |
- DCHECK(node2); |
- |
- // Keep folder nodes before non-folder nodes. |
- if (node1->is_folder() != node2->is_folder()) |
- return node1->is_folder(); |
- |
- // Truncate bookmark titles in the form sync does internally to avoid |
- // mismatches due to sync munging titles. |
- std::string title1 = base::UTF16ToUTF8(node1->GetTitle()); |
- syncer::SyncAPINameToServerName(title1, &title1); |
- base::TruncateUTF8ToByteSize(title1, kTitleLimitBytes, &title1); |
- |
- std::string title2 = base::UTF16ToUTF8(node2->GetTitle()); |
- syncer::SyncAPINameToServerName(title2, &title2); |
- base::TruncateUTF8ToByteSize(title2, kTitleLimitBytes, &title2); |
- |
- int result = title1.compare(title2); |
- if (result != 0) |
- return result < 0; |
- |
- return node1->url() < node2->url(); |
- } |
-}; |
- |
// Provides the following abstraction: given a parent bookmark node, find best |
// matching child node for many sync nodes. |
class BookmarkNodeFinder { |
@@ -113,10 +81,21 @@ class BookmarkNodeFinder { |
bool is_folder); |
private: |
- typedef std::multiset<const BookmarkNode*, BookmarkComparer> BookmarkNodesSet; |
+ // Maps bookmark node titles to instances, duplicates allowed. |
+ // Titles are converted to the sync internal format before |
+ // being used as keys for the map. |
+ typedef base::hash_multimap<std::string, |
+ const BookmarkNode*> BookmarkNodeMap; |
+ typedef std::pair<BookmarkNodeMap::iterator, |
+ BookmarkNodeMap::iterator> BookmarkNodeRange; |
+ |
+ // Converts and truncates bookmark titles in the form sync does internally |
+ // to avoid mismatches due to sync munging titles. |
+ void ConvertTitleToSyncInternalFormat( |
+ const std::string& input, std::string* output); |
const BookmarkNode* parent_node_; |
- BookmarkNodesSet child_nodes_; |
+ BookmarkNodeMap child_nodes_; |
DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder); |
}; |
@@ -141,29 +120,42 @@ class ScopedAssociationUpdater { |
BookmarkNodeFinder::BookmarkNodeFinder(const BookmarkNode* parent_node) |
: parent_node_(parent_node) { |
for (int i = 0; i < parent_node_->child_count(); ++i) { |
- child_nodes_.insert(parent_node_->GetChild(i)); |
+ const BookmarkNode* child_node = parent_node_->GetChild(i); |
+ |
+ std::string title = base::UTF16ToUTF8(child_node->GetTitle()); |
+ ConvertTitleToSyncInternalFormat(title, &title); |
+ |
+ child_nodes_.insert(std::make_pair(title, child_node)); |
} |
} |
const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode( |
const GURL& url, const std::string& title, bool is_folder) { |
- // Create a bookmark node from the given bookmark attributes. |
- BookmarkNode temp_node(url); |
- temp_node.SetTitle(base::UTF8ToUTF16(title)); |
- if (is_folder) |
- temp_node.set_type(BookmarkNode::FOLDER); |
- else |
- temp_node.set_type(BookmarkNode::URL); |
- |
- const BookmarkNode* result = NULL; |
- BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node); |
- if (iter != child_nodes_.end()) { |
- result = *iter; |
- // Remove the matched node so we don't match with it again. |
- child_nodes_.erase(iter); |
+ // First lookup a range of bookmarks with the same title. |
+ std::string adjusted_title; |
+ ConvertTitleToSyncInternalFormat(title, &adjusted_title); |
+ BookmarkNodeRange range = child_nodes_.equal_range(adjusted_title); |
+ for (BookmarkNodeMap::iterator iter = range.first; |
+ iter != range.second; |
+ ++iter) { |
+ |
+ // Then within the range match the node by the folder bit |
+ // and the url. |
+ const BookmarkNode* node = iter->second; |
+ if (is_folder == node->is_folder() && url == node->url()) { |
+ // Remove the matched node so we don't match with it again. |
+ child_nodes_.erase(iter); |
+ return node; |
+ } |
} |
- return result; |
+ return NULL; |
+} |
+ |
+void BookmarkNodeFinder::ConvertTitleToSyncInternalFormat( |
+ const std::string& input, std::string* output) { |
+ syncer::SyncAPINameToServerName(input, output); |
+ base::TruncateUTF8ToByteSize(*output, kTitleLimitBytes, output); |
} |
// Helper class to build an index of bookmark nodes by their IDs. |