Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(424)

Side by Side Diff: chrome/browser/sync/glue/bookmark_model_associator.cc

Issue 904083002: Use external ID to match native model nodes during bookmark association. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed CR feedback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/glue/bookmark_model_associator.h" 5 #include "chrome/browser/sync/glue/bookmark_model_associator.h"
6 6
7 #include <stack> 7 #include <stack>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 const int kTitleLimitBytes = 255; 69 const int kTitleLimitBytes = 255;
70 70
71 // Provides the following abstraction: given a parent bookmark node, find best 71 // Provides the following abstraction: given a parent bookmark node, find best
72 // matching child node for many sync nodes. 72 // matching child node for many sync nodes.
73 class BookmarkNodeFinder { 73 class BookmarkNodeFinder {
74 public: 74 public:
75 // Creates an instance with the given parent bookmark node. 75 // Creates an instance with the given parent bookmark node.
76 explicit BookmarkNodeFinder(const BookmarkNode* parent_node); 76 explicit BookmarkNodeFinder(const BookmarkNode* parent_node);
77 77
78 // Finds the bookmark node that matches the given url, title and folder 78 // Finds the bookmark node that matches the given url, title and folder
79 // attribute. Returns the matching node if one exists; NULL otherwise. If a 79 // attribute. Returns the matching node if one exists; NULL otherwise.
80 // matching node is found, it's removed for further matches. 80 // If there are multiple matches then a node with ID matching |preferred_id|
81 // is returned; otherwise the first matching node is returned.
82 // If a matching node is found, it's removed for further matches.
81 const BookmarkNode* FindBookmarkNode(const GURL& url, 83 const BookmarkNode* FindBookmarkNode(const GURL& url,
82 const std::string& title, 84 const std::string& title,
83 bool is_folder); 85 bool is_folder,
86 int64 preferred_id);
87
88 // Returns true if |bookmark_node| matches the specified |url|,
89 // |title|, and |is_folder| flags.
90 static bool NodeMatches(const BookmarkNode* bookmark_node,
91 const GURL& url,
92 const std::string& title,
93 bool is_folder);
84 94
85 private: 95 private:
86 // Maps bookmark node titles to instances, duplicates allowed. 96 // Maps bookmark node titles to instances, duplicates allowed.
87 // Titles are converted to the sync internal format before 97 // Titles are converted to the sync internal format before
88 // being used as keys for the map. 98 // being used as keys for the map.
89 typedef base::hash_multimap<std::string, 99 typedef base::hash_multimap<std::string,
90 const BookmarkNode*> BookmarkNodeMap; 100 const BookmarkNode*> BookmarkNodeMap;
91 typedef std::pair<BookmarkNodeMap::iterator, 101 typedef std::pair<BookmarkNodeMap::iterator,
92 BookmarkNodeMap::iterator> BookmarkNodeRange; 102 BookmarkNodeMap::iterator> BookmarkNodeRange;
93 103
94 // Converts and truncates bookmark titles in the form sync does internally 104 // Converts and truncates bookmark titles in the form sync does internally
95 // to avoid mismatches due to sync munging titles. 105 // to avoid mismatches due to sync munging titles.
96 void ConvertTitleToSyncInternalFormat( 106 static void ConvertTitleToSyncInternalFormat(const std::string& input,
97 const std::string& input, std::string* output); 107 std::string* output);
98 108
99 const BookmarkNode* parent_node_; 109 const BookmarkNode* parent_node_;
100 BookmarkNodeMap child_nodes_; 110 BookmarkNodeMap child_nodes_;
101 111
102 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder); 112 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder);
103 }; 113 };
104 114
105 class ScopedAssociationUpdater { 115 class ScopedAssociationUpdater {
106 public: 116 public:
107 explicit ScopedAssociationUpdater(BookmarkModel* model) { 117 explicit ScopedAssociationUpdater(BookmarkModel* model) {
(...skipping 17 matching lines...) Expand all
125 const BookmarkNode* child_node = parent_node_->GetChild(i); 135 const BookmarkNode* child_node = parent_node_->GetChild(i);
126 136
127 std::string title = base::UTF16ToUTF8(child_node->GetTitle()); 137 std::string title = base::UTF16ToUTF8(child_node->GetTitle());
128 ConvertTitleToSyncInternalFormat(title, &title); 138 ConvertTitleToSyncInternalFormat(title, &title);
129 139
130 child_nodes_.insert(std::make_pair(title, child_node)); 140 child_nodes_.insert(std::make_pair(title, child_node));
131 } 141 }
132 } 142 }
133 143
134 const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode( 144 const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode(
135 const GURL& url, const std::string& title, bool is_folder) { 145 const GURL& url,
146 const std::string& title,
147 bool is_folder,
148 int64 preferred_id) {
149 const BookmarkNode* match = nullptr;
150
136 // First lookup a range of bookmarks with the same title. 151 // First lookup a range of bookmarks with the same title.
137 std::string adjusted_title; 152 std::string adjusted_title;
138 ConvertTitleToSyncInternalFormat(title, &adjusted_title); 153 ConvertTitleToSyncInternalFormat(title, &adjusted_title);
139 BookmarkNodeRange range = child_nodes_.equal_range(adjusted_title); 154 BookmarkNodeRange range = child_nodes_.equal_range(adjusted_title);
155 BookmarkNodeMap::iterator match_iter = range.second;
140 for (BookmarkNodeMap::iterator iter = range.first; 156 for (BookmarkNodeMap::iterator iter = range.first;
141 iter != range.second; 157 iter != range.second;
142 ++iter) { 158 ++iter) {
143
144 // Then within the range match the node by the folder bit 159 // Then within the range match the node by the folder bit
145 // and the url. 160 // and the url.
146 const BookmarkNode* node = iter->second; 161 const BookmarkNode* node = iter->second;
147 if (is_folder == node->is_folder() && url == node->url()) { 162 if (is_folder == node->is_folder() && url == node->url()) {
148 // Remove the matched node so we don't match with it again. 163 if (node->id() == preferred_id || preferred_id == 0) {
149 child_nodes_.erase(iter); 164 // Preferred match - use this node.
150 return node; 165 match = node;
166 match_iter = iter;
167 break;
168 } else if (match == nullptr) {
169 // First match - continue iterating.
170 match = node;
171 match_iter = iter;
172 }
151 } 173 }
152 } 174 }
153 175
154 return NULL; 176 if (match_iter != range.second) {
177 // Remove the matched node so we don't match with it again.
178 child_nodes_.erase(match_iter);
179 }
180
181 return match;
155 } 182 }
156 183
184 /* static */
185 bool BookmarkNodeFinder::NodeMatches(const BookmarkNode* bookmark_node,
186 const GURL& url,
187 const std::string& title,
188 bool is_folder) {
189 if (url != bookmark_node->url() || is_folder != bookmark_node->is_folder()) {
190 return false;
191 }
192
193 // The title passed to this method comes from a sync directory entry.
194 // The following two lines are needed to make the native bookmark title
195 // comparable. The same conversion is used in BookmarkNodeFinder constructor.
196 std::string bookmark_title = base::UTF16ToUTF8(bookmark_node->GetTitle());
197 ConvertTitleToSyncInternalFormat(bookmark_title, &bookmark_title);
198 return title == bookmark_title;
199 }
200
201 /* static */
157 void BookmarkNodeFinder::ConvertTitleToSyncInternalFormat( 202 void BookmarkNodeFinder::ConvertTitleToSyncInternalFormat(
158 const std::string& input, std::string* output) { 203 const std::string& input, std::string* output) {
159 syncer::SyncAPINameToServerName(input, output); 204 syncer::SyncAPINameToServerName(input, output);
160 base::TruncateUTF8ToByteSize(*output, kTitleLimitBytes, output); 205 base::TruncateUTF8ToByteSize(*output, kTitleLimitBytes, output);
161 } 206 }
162 207
163 // Helper class to build an index of bookmark nodes by their IDs. 208 // Helper class to build an index of bookmark nodes by their IDs.
164 class BookmarkNodeIdIndex { 209 class BookmarkNodeIdIndex {
165 public: 210 public:
166 BookmarkNodeIdIndex() { } 211 BookmarkNodeIdIndex() { }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 384 }
340 385
341 // Sync model has user created nodes if any of the permanent nodes has 386 // Sync model has user created nodes if any of the permanent nodes has
342 // children. 387 // children.
343 *has_nodes = bookmark_bar_node.HasChildren() || 388 *has_nodes = bookmark_bar_node.HasChildren() ||
344 other_bookmarks_node.HasChildren() || 389 other_bookmarks_node.HasChildren() ||
345 (has_mobile_folder && mobile_bookmarks_node.HasChildren()); 390 (has_mobile_folder && mobile_bookmarks_node.HasChildren());
346 return true; 391 return true;
347 } 392 }
348 393
349 bool BookmarkModelAssociator::NodesMatch(
350 const BookmarkNode* bookmark,
351 const syncer::BaseNode* sync_node) const {
352 std::string truncated_title = base::UTF16ToUTF8(bookmark->GetTitle());
353 base::TruncateUTF8ToByteSize(truncated_title,
354 kTitleLimitBytes,
355 &truncated_title);
356 if (truncated_title != sync_node->GetTitle())
357 return false;
358 if (bookmark->is_folder() != sync_node->GetIsFolder())
359 return false;
360 if (bookmark->is_url()) {
361 if (bookmark->url() != GURL(sync_node->GetBookmarkSpecifics().url()))
362 return false;
363 }
364 // Don't compare favicons here, because they are not really
365 // user-updated and we don't have versioning information -- a site changing
366 // its favicon shouldn't result in a bookmark mismatch.
367 return true;
368 }
369
370 bool BookmarkModelAssociator::AssociateTaggedPermanentNode( 394 bool BookmarkModelAssociator::AssociateTaggedPermanentNode(
371 const BookmarkNode* permanent_node, const std::string&tag) { 395 const BookmarkNode* permanent_node, const std::string&tag) {
372 // Do nothing if |permanent_node| is already initialized and associated. 396 // Do nothing if |permanent_node| is already initialized and associated.
373 int64 sync_id = GetSyncIdFromChromeId(permanent_node->id()); 397 int64 sync_id = GetSyncIdFromChromeId(permanent_node->id());
374 if (sync_id != syncer::kInvalidId) 398 if (sync_id != syncer::kInvalidId)
375 return true; 399 return true;
376 if (!GetSyncIdForTaggedNode(tag, &sync_id)) 400 if (!GetSyncIdForTaggedNode(tag, &sync_id))
377 return false; 401 return false;
378 402
379 Associate(permanent_node, sync_id); 403 Associate(permanent_node, sync_id);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 // Match up the roots and recursively do the following: 441 // Match up the roots and recursively do the following:
418 // * For each sync node for the current sync parent node, find the best 442 // * For each sync node for the current sync parent node, find the best
419 // matching bookmark node under the corresponding bookmark parent node. 443 // matching bookmark node under the corresponding bookmark parent node.
420 // If no matching node is found, create a new bookmark node in the same 444 // If no matching node is found, create a new bookmark node in the same
421 // position as the corresponding sync node. 445 // position as the corresponding sync node.
422 // If a matching node is found, update the properties of it from the 446 // If a matching node is found, update the properties of it from the
423 // corresponding sync node. 447 // corresponding sync node.
424 // * When all children sync nodes are done, add the extra children bookmark 448 // * When all children sync nodes are done, add the extra children bookmark
425 // nodes to the sync parent node. 449 // nodes to the sync parent node.
426 // 450 //
427 // This algorithm will do a good job of merging when folder names are a good 451 // The best match algorithm uses folder title or bookmark title/url to
428 // indicator of the two folders being the same. It will handle reordering and 452 // perform the primary match. If there are multiple match candidates it
429 // new node addition very well (without creating duplicates). 453 // selects the preferred one based on sync node external ID match to the
430 // This algorithm will not do well if the folder name has changes but the 454 // bookmark folder ID.
431 // children under them are all the same.
432 455
433 DCHECK(bookmark_model_->loaded()); 456 DCHECK(bookmark_model_->loaded());
434 457
435 // To prime our association, we associate the top-level nodes, Bookmark Bar 458 // To prime our association, we associate the top-level nodes, Bookmark Bar
436 // and Other Bookmarks. 459 // and Other Bookmarks.
437 if (!AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(), 460 if (!AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(),
438 kBookmarkBarTag)) { 461 kBookmarkBarTag)) {
439 return unrecoverable_error_handler_->CreateAndUploadError( 462 return unrecoverable_error_handler_->CreateAndUploadError(
440 FROM_HERE, 463 FROM_HERE,
441 "Bookmark bar node not found", 464 "Bookmark bar node not found",
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 syncer::WriteTransaction trans(FROM_HERE, user_share_); 508 syncer::WriteTransaction trans(FROM_HERE, user_share_);
486 syncer::ReadNode bm_root(&trans); 509 syncer::ReadNode bm_root(&trans);
487 if (bm_root.InitTypeRoot(syncer::BOOKMARKS) == syncer::BaseNode::INIT_OK) { 510 if (bm_root.InitTypeRoot(syncer::BOOKMARKS) == syncer::BaseNode::INIT_OK) {
488 syncer_merge_result->set_num_items_before_association( 511 syncer_merge_result->set_num_items_before_association(
489 bm_root.GetTotalNodeCount()); 512 bm_root.GetTotalNodeCount());
490 } 513 }
491 local_merge_result->set_num_items_before_association( 514 local_merge_result->set_num_items_before_association(
492 bookmark_model_->root_node()->GetTotalNodeCount()); 515 bookmark_model_->root_node()->GetTotalNodeCount());
493 516
494 // Remove obsolete bookmarks according to sync delete journal. 517 // Remove obsolete bookmarks according to sync delete journal.
518 // TODO (stanisc): crbug.com/456876: rewrite this to avoid a separate
519 // traversal and instead perform deletes at the end of the loop below where
520 // the unmatched bookmark nodes are created as sync nodes.
495 local_merge_result->set_num_items_deleted( 521 local_merge_result->set_num_items_deleted(
496 ApplyDeletesFromSyncJournal(&trans)); 522 ApplyDeletesFromSyncJournal(&trans));
497 523
498 while (!dfs_stack.empty()) { 524 while (!dfs_stack.empty()) {
499 int64 sync_parent_id = dfs_stack.top(); 525 int64 sync_parent_id = dfs_stack.top();
500 dfs_stack.pop(); 526 dfs_stack.pop();
501 527
502 syncer::ReadNode sync_parent(&trans); 528 syncer::ReadNode sync_parent(&trans);
503 if (sync_parent.InitByIdLookup(sync_parent_id) != 529 if (sync_parent.InitByIdLookup(sync_parent_id) !=
504 syncer::BaseNode::INIT_OK) { 530 syncer::BaseNode::INIT_OK) {
(...skipping 22 matching lines...) Expand all
527 int64 sync_child_id = *it; 553 int64 sync_child_id = *it;
528 syncer::ReadNode sync_child_node(&trans); 554 syncer::ReadNode sync_child_node(&trans);
529 if (sync_child_node.InitByIdLookup(sync_child_id) != 555 if (sync_child_node.InitByIdLookup(sync_child_id) !=
530 syncer::BaseNode::INIT_OK) { 556 syncer::BaseNode::INIT_OK) {
531 return unrecoverable_error_handler_->CreateAndUploadError( 557 return unrecoverable_error_handler_->CreateAndUploadError(
532 FROM_HERE, 558 FROM_HERE,
533 "Failed to lookup node.", 559 "Failed to lookup node.",
534 model_type()); 560 model_type());
535 } 561 }
536 562
537 const BookmarkNode* child_node = NULL; 563 const BookmarkNode* child_node = node_finder.FindBookmarkNode(
538 child_node = node_finder.FindBookmarkNode(
539 GURL(sync_child_node.GetBookmarkSpecifics().url()), 564 GURL(sync_child_node.GetBookmarkSpecifics().url()),
540 sync_child_node.GetTitle(), 565 sync_child_node.GetTitle(), sync_child_node.GetIsFolder(),
541 sync_child_node.GetIsFolder()); 566 sync_child_node.GetExternalId());
542 if (child_node) { 567 if (child_node) {
543 Associate(child_node, sync_child_id); 568 Associate(child_node, sync_child_id);
544 569
545 // All bookmarks are currently modified at association time, even if 570 // All bookmarks are currently modified at association time, even if
546 // nothing has changed. 571 // nothing has changed.
547 // TODO(sync): Only modify the bookmark model if necessary. 572 // TODO(sync): Only modify the bookmark model if necessary.
548 BookmarkChangeProcessor::UpdateBookmarkWithSyncData( 573 BookmarkChangeProcessor::UpdateBookmarkWithSyncData(
549 sync_child_node, bookmark_model_, child_node, profile_); 574 sync_child_node, bookmark_model_, child_node, profile_);
550 bookmark_model_->Move(child_node, parent_node, index); 575 bookmark_model_->Move(child_node, parent_node, index);
551 local_merge_result->set_num_items_modified( 576 local_merge_result->set_num_items_modified(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 int64 BookmarkModelAssociator::ApplyDeletesFromSyncJournal( 634 int64 BookmarkModelAssociator::ApplyDeletesFromSyncJournal(
610 syncer::BaseTransaction* trans) { 635 syncer::BaseTransaction* trans) {
611 int64 num_bookmark_deleted = 0; 636 int64 num_bookmark_deleted = 0;
612 637
613 syncer::BookmarkDeleteJournalList bk_delete_journals; 638 syncer::BookmarkDeleteJournalList bk_delete_journals;
614 syncer::DeleteJournal::GetBookmarkDeleteJournals(trans, &bk_delete_journals); 639 syncer::DeleteJournal::GetBookmarkDeleteJournals(trans, &bk_delete_journals);
615 if (bk_delete_journals.empty()) 640 if (bk_delete_journals.empty())
616 return 0; 641 return 0;
617 size_t num_journals_unmatched = bk_delete_journals.size(); 642 size_t num_journals_unmatched = bk_delete_journals.size();
618 643
644 // Make a set of all external IDs in the delete journal,
645 // ignore entries with unset external IDs.
646 std::set<int64> journaled_external_ids;
647 for (size_t i = 0; i < num_journals_unmatched; i++) {
648 if (bk_delete_journals[i].external_id != 0)
649 journaled_external_ids.insert(bk_delete_journals[i].external_id);
650 }
651
619 // Check bookmark model from top to bottom. 652 // Check bookmark model from top to bottom.
620 std::stack<const BookmarkNode*> dfs_stack; 653 std::stack<const BookmarkNode*> dfs_stack;
621 dfs_stack.push(bookmark_model_->bookmark_bar_node()); 654 dfs_stack.push(bookmark_model_->bookmark_bar_node());
622 dfs_stack.push(bookmark_model_->other_node()); 655 dfs_stack.push(bookmark_model_->other_node());
623 if (expect_mobile_bookmarks_folder_) 656 if (expect_mobile_bookmarks_folder_)
624 dfs_stack.push(bookmark_model_->mobile_node()); 657 dfs_stack.push(bookmark_model_->mobile_node());
625 // Note: the root node may have additional extra nodes. Currently none of 658 // Note: the root node may have additional extra nodes. Currently none of
626 // them are meant to sync. 659 // them are meant to sync.
627 660
628 // Remember folders that match delete journals in first pass but don't delete 661 // Remember folders that match delete journals in first pass but don't delete
629 // them in case there are bookmarks left under them. After non-folder 662 // them in case there are bookmarks left under them. After non-folder
630 // bookmarks are removed in first pass, recheck the folders in reverse order 663 // bookmarks are removed in first pass, recheck the folders in reverse order
631 // to remove empty ones. 664 // to remove empty ones.
632 FolderInfoList folders_matched; 665 FolderInfoList folders_matched;
633 while (!dfs_stack.empty()) { 666 while (!dfs_stack.empty() && num_journals_unmatched > 0) {
634 const BookmarkNode* parent = dfs_stack.top(); 667 const BookmarkNode* parent = dfs_stack.top();
635 dfs_stack.pop(); 668 dfs_stack.pop();
669 DCHECK(parent->is_folder());
636 670
637 BookmarkNodeFinder finder(parent); 671 // Enumerate folder children in reverse order to make it easier to remove
638 // Iterate through journals from back to front. Remove matched journal by 672 // bookmarks matching entries in the delete journal.
639 // moving an unmatched journal at the tail to its position so that we can 673 for (int child_index = parent->child_count() - 1;
640 // read unmatched journals off the head in next loop. 674 child_index >= 0 && num_journals_unmatched > 0; --child_index) {
641 for (int i = num_journals_unmatched - 1; i >= 0; --i) { 675 const BookmarkNode* child = parent->GetChild(child_index);
642 const BookmarkNode* child = finder.FindBookmarkNode( 676 if (child->is_folder())
643 GURL(bk_delete_journals[i].specifics.bookmark().url()), 677 dfs_stack.push(child);
644 bk_delete_journals[i].specifics.bookmark().title(), 678
645 bk_delete_journals[i].is_folder); 679 if (journaled_external_ids.find(child->id()) ==
646 if (child) { 680 journaled_external_ids.end()) {
647 if (child->is_folder()) { 681 // Skip bookmark node which id is not in the set of external IDs.
648 // Remember matched folder without removing and delete only empty 682 continue;
649 // ones later. 683 }
650 folders_matched.push_back(FolderInfo(child, parent, 684
651 bk_delete_journals[i].id)); 685 // Iterate through the journal entries from back to front. Remove matched
652 } else { 686 // journal by moving an unmatched entry at the tail to the matched
653 bookmark_model_->Remove(parent, parent->GetIndexOf(child)); 687 // position so that we can read unmatched entries off the head in next
654 ++num_bookmark_deleted; 688 // loop.
689 for (int journal_index = num_journals_unmatched - 1; journal_index >= 0;
690 --journal_index) {
691 const syncer::BookmarkDeleteJournal& delete_entry =
692 bk_delete_journals[journal_index];
693 if (child->id() == delete_entry.external_id &&
694 BookmarkNodeFinder::NodeMatches(
695 child, GURL(delete_entry.specifics.bookmark().url()),
696 delete_entry.specifics.bookmark().title(),
697 delete_entry.is_folder)) {
698 if (child->is_folder()) {
699 // Remember matched folder without removing and delete only empty
700 // ones later.
701 folders_matched.push_back(
702 FolderInfo(child, parent, delete_entry.id));
703 } else {
704 bookmark_model_->Remove(parent, child_index);
705 ++num_bookmark_deleted;
706 }
707 // Move unmatched journal here and decrement counter.
708 bk_delete_journals[journal_index] =
709 bk_delete_journals[--num_journals_unmatched];
710 break;
655 } 711 }
656 // Move unmatched journal here and decrement counter.
657 bk_delete_journals[i] = bk_delete_journals[--num_journals_unmatched];
658 } 712 }
659 } 713 }
660 if (num_journals_unmatched == 0)
661 break;
662
663 for (int i = 0; i < parent->child_count(); ++i) {
664 if (parent->GetChild(i)->is_folder())
665 dfs_stack.push(parent->GetChild(i));
666 }
667 } 714 }
668 715
669 // Ids of sync nodes not found in bookmark model, meaning the deletions are 716 // Ids of sync nodes not found in bookmark model, meaning the deletions are
670 // persisted and correponding delete journals can be dropped. 717 // persisted and correponding delete journals can be dropped.
671 std::set<int64> journals_to_purge; 718 std::set<int64> journals_to_purge;
672 719
673 // Remove empty folders from bottom to top. 720 // Remove empty folders from bottom to top.
674 for (FolderInfoList::reverse_iterator it = folders_matched.rbegin(); 721 for (FolderInfoList::reverse_iterator it = folders_matched.rbegin();
675 it != folders_matched.rend(); ++it) { 722 it != folders_matched.rend(); ++it) {
676 if (it->folder->child_count() == 0) { 723 if (it->folder->child_count() == 0) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 syncer::SyncError::PERSISTENCE_ERROR, 834 syncer::SyncError::PERSISTENCE_ERROR,
788 message, 835 message,
789 syncer::BOOKMARKS); 836 syncer::BOOKMARKS);
790 } 837 }
791 } 838 }
792 } 839 }
793 return syncer::SyncError(); 840 return syncer::SyncError();
794 } 841 }
795 842
796 } // namespace browser_sync 843 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/bookmark_model_associator.h ('k') | chrome/browser/sync/profile_sync_service_bookmark_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698