| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // Provides the following abstraction: given a parent bookmark node, find best | 77 // Provides the following abstraction: given a parent bookmark node, find best |
| 78 // matching child node for many sync nodes. | 78 // matching child node for many sync nodes. |
| 79 class BookmarkNodeFinder { | 79 class BookmarkNodeFinder { |
| 80 public: | 80 public: |
| 81 // Creates an instance with the given parent bookmark node. | 81 // Creates an instance with the given parent bookmark node. |
| 82 explicit BookmarkNodeFinder(const BookmarkNode* parent_node); | 82 explicit BookmarkNodeFinder(const BookmarkNode* parent_node); |
| 83 | 83 |
| 84 // Finds best matching node for the given sync node. | 84 // Finds best matching node for the given sync node. |
| 85 // Returns the matching node if one exists; NULL otherwise. If a matching | 85 // Returns the matching node if one exists; NULL otherwise. If a matching |
| 86 // node is found, it's removed for further matches. | 86 // node is found, it's removed for further matches. |
| 87 const BookmarkNode* FindBookmarkNode(const csync::BaseNode& sync_node); | 87 const BookmarkNode* FindBookmarkNode(const syncer::BaseNode& sync_node); |
| 88 | 88 |
| 89 private: | 89 private: |
| 90 typedef std::multiset<const BookmarkNode*, BookmarkComparer> BookmarkNodesSet; | 90 typedef std::multiset<const BookmarkNode*, BookmarkComparer> BookmarkNodesSet; |
| 91 | 91 |
| 92 const BookmarkNode* parent_node_; | 92 const BookmarkNode* parent_node_; |
| 93 BookmarkNodesSet child_nodes_; | 93 BookmarkNodesSet child_nodes_; |
| 94 | 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder); | 95 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder); |
| 96 }; | 96 }; |
| 97 | 97 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 113 }; | 113 }; |
| 114 | 114 |
| 115 BookmarkNodeFinder::BookmarkNodeFinder(const BookmarkNode* parent_node) | 115 BookmarkNodeFinder::BookmarkNodeFinder(const BookmarkNode* parent_node) |
| 116 : parent_node_(parent_node) { | 116 : parent_node_(parent_node) { |
| 117 for (int i = 0; i < parent_node_->child_count(); ++i) { | 117 for (int i = 0; i < parent_node_->child_count(); ++i) { |
| 118 child_nodes_.insert(parent_node_->GetChild(i)); | 118 child_nodes_.insert(parent_node_->GetChild(i)); |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode( | 122 const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode( |
| 123 const csync::BaseNode& sync_node) { | 123 const syncer::BaseNode& sync_node) { |
| 124 // Create a bookmark node from the given sync node. | 124 // Create a bookmark node from the given sync node. |
| 125 BookmarkNode temp_node(sync_node.GetURL()); | 125 BookmarkNode temp_node(sync_node.GetURL()); |
| 126 temp_node.SetTitle(UTF8ToUTF16(sync_node.GetTitle())); | 126 temp_node.SetTitle(UTF8ToUTF16(sync_node.GetTitle())); |
| 127 if (sync_node.GetIsFolder()) | 127 if (sync_node.GetIsFolder()) |
| 128 temp_node.set_type(BookmarkNode::FOLDER); | 128 temp_node.set_type(BookmarkNode::FOLDER); |
| 129 else | 129 else |
| 130 temp_node.set_type(BookmarkNode::URL); | 130 temp_node.set_type(BookmarkNode::URL); |
| 131 | 131 |
| 132 const BookmarkNode* result = NULL; | 132 const BookmarkNode* result = NULL; |
| 133 BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node); | 133 BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 AddAll(node->GetChild(i)); | 178 AddAll(node->GetChild(i)); |
| 179 } | 179 } |
| 180 | 180 |
| 181 const BookmarkNode* BookmarkNodeIdIndex::Find(int64 id) const { | 181 const BookmarkNode* BookmarkNodeIdIndex::Find(int64 id) const { |
| 182 BookmarkIdMap::const_iterator iter = node_index_.find(id); | 182 BookmarkIdMap::const_iterator iter = node_index_.find(id); |
| 183 return iter == node_index_.end() ? NULL : iter->second; | 183 return iter == node_index_.end() ? NULL : iter->second; |
| 184 } | 184 } |
| 185 | 185 |
| 186 BookmarkModelAssociator::BookmarkModelAssociator( | 186 BookmarkModelAssociator::BookmarkModelAssociator( |
| 187 BookmarkModel* bookmark_model, | 187 BookmarkModel* bookmark_model, |
| 188 csync::UserShare* user_share, | 188 syncer::UserShare* user_share, |
| 189 DataTypeErrorHandler* unrecoverable_error_handler, | 189 DataTypeErrorHandler* unrecoverable_error_handler, |
| 190 bool expect_mobile_bookmarks_folder) | 190 bool expect_mobile_bookmarks_folder) |
| 191 : bookmark_model_(bookmark_model), | 191 : bookmark_model_(bookmark_model), |
| 192 user_share_(user_share), | 192 user_share_(user_share), |
| 193 unrecoverable_error_handler_(unrecoverable_error_handler), | 193 unrecoverable_error_handler_(unrecoverable_error_handler), |
| 194 expect_mobile_bookmarks_folder_(expect_mobile_bookmarks_folder), | 194 expect_mobile_bookmarks_folder_(expect_mobile_bookmarks_folder), |
| 195 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 195 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 196 number_of_new_sync_nodes_created_at_association_(0) { | 196 number_of_new_sync_nodes_created_at_association_(0) { |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 198 DCHECK(bookmark_model_); | 198 DCHECK(bookmark_model_); |
| 199 DCHECK(user_share_); | 199 DCHECK(user_share_); |
| 200 DCHECK(unrecoverable_error_handler_); | 200 DCHECK(unrecoverable_error_handler_); |
| 201 } | 201 } |
| 202 | 202 |
| 203 BookmarkModelAssociator::~BookmarkModelAssociator() { | 203 BookmarkModelAssociator::~BookmarkModelAssociator() { |
| 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 205 } | 205 } |
| 206 | 206 |
| 207 void BookmarkModelAssociator::UpdatePermanentNodeVisibility() { | 207 void BookmarkModelAssociator::UpdatePermanentNodeVisibility() { |
| 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 209 DCHECK(bookmark_model_->IsLoaded()); | 209 DCHECK(bookmark_model_->IsLoaded()); |
| 210 | 210 |
| 211 bookmark_model_->SetPermanentNodeVisible( | 211 bookmark_model_->SetPermanentNodeVisible( |
| 212 BookmarkNode::MOBILE, | 212 BookmarkNode::MOBILE, |
| 213 id_map_.find(bookmark_model_->mobile_node()->id()) != id_map_.end()); | 213 id_map_.find(bookmark_model_->mobile_node()->id()) != id_map_.end()); |
| 214 } | 214 } |
| 215 | 215 |
| 216 csync::SyncError BookmarkModelAssociator::DisassociateModels() { | 216 syncer::SyncError BookmarkModelAssociator::DisassociateModels() { |
| 217 id_map_.clear(); | 217 id_map_.clear(); |
| 218 id_map_inverse_.clear(); | 218 id_map_inverse_.clear(); |
| 219 dirty_associations_sync_ids_.clear(); | 219 dirty_associations_sync_ids_.clear(); |
| 220 return csync::SyncError(); | 220 return syncer::SyncError(); |
| 221 } | 221 } |
| 222 | 222 |
| 223 int64 BookmarkModelAssociator::GetSyncIdFromChromeId(const int64& node_id) { | 223 int64 BookmarkModelAssociator::GetSyncIdFromChromeId(const int64& node_id) { |
| 224 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id); | 224 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id); |
| 225 return iter == id_map_.end() ? csync::kInvalidId : iter->second; | 225 return iter == id_map_.end() ? syncer::kInvalidId : iter->second; |
| 226 } | 226 } |
| 227 | 227 |
| 228 const BookmarkNode* BookmarkModelAssociator::GetChromeNodeFromSyncId( | 228 const BookmarkNode* BookmarkModelAssociator::GetChromeNodeFromSyncId( |
| 229 int64 sync_id) { | 229 int64 sync_id) { |
| 230 SyncIdToBookmarkNodeMap::const_iterator iter = id_map_inverse_.find(sync_id); | 230 SyncIdToBookmarkNodeMap::const_iterator iter = id_map_inverse_.find(sync_id); |
| 231 return iter == id_map_inverse_.end() ? NULL : iter->second; | 231 return iter == id_map_inverse_.end() ? NULL : iter->second; |
| 232 } | 232 } |
| 233 | 233 |
| 234 bool BookmarkModelAssociator::InitSyncNodeFromChromeId( | 234 bool BookmarkModelAssociator::InitSyncNodeFromChromeId( |
| 235 const int64& node_id, | 235 const int64& node_id, |
| 236 csync::BaseNode* sync_node) { | 236 syncer::BaseNode* sync_node) { |
| 237 DCHECK(sync_node); | 237 DCHECK(sync_node); |
| 238 int64 sync_id = GetSyncIdFromChromeId(node_id); | 238 int64 sync_id = GetSyncIdFromChromeId(node_id); |
| 239 if (sync_id == csync::kInvalidId) | 239 if (sync_id == syncer::kInvalidId) |
| 240 return false; | 240 return false; |
| 241 if (sync_node->InitByIdLookup(sync_id) != csync::BaseNode::INIT_OK) | 241 if (sync_node->InitByIdLookup(sync_id) != syncer::BaseNode::INIT_OK) |
| 242 return false; | 242 return false; |
| 243 DCHECK(sync_node->GetId() == sync_id); | 243 DCHECK(sync_node->GetId() == sync_id); |
| 244 return true; | 244 return true; |
| 245 } | 245 } |
| 246 | 246 |
| 247 void BookmarkModelAssociator::Associate(const BookmarkNode* node, | 247 void BookmarkModelAssociator::Associate(const BookmarkNode* node, |
| 248 int64 sync_id) { | 248 int64 sync_id) { |
| 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 250 int64 node_id = node->id(); | 250 int64 node_id = node->id(); |
| 251 DCHECK_NE(sync_id, csync::kInvalidId); | 251 DCHECK_NE(sync_id, syncer::kInvalidId); |
| 252 DCHECK(id_map_.find(node_id) == id_map_.end()); | 252 DCHECK(id_map_.find(node_id) == id_map_.end()); |
| 253 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); | 253 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); |
| 254 id_map_[node_id] = sync_id; | 254 id_map_[node_id] = sync_id; |
| 255 id_map_inverse_[sync_id] = node; | 255 id_map_inverse_[sync_id] = node; |
| 256 dirty_associations_sync_ids_.insert(sync_id); | 256 dirty_associations_sync_ids_.insert(sync_id); |
| 257 PostPersistAssociationsTask(); | 257 PostPersistAssociationsTask(); |
| 258 UpdatePermanentNodeVisibility(); | 258 UpdatePermanentNodeVisibility(); |
| 259 } | 259 } |
| 260 | 260 |
| 261 void BookmarkModelAssociator::Disassociate(int64 sync_id) { | 261 void BookmarkModelAssociator::Disassociate(int64 sync_id) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 278 } | 278 } |
| 279 int64 other_bookmarks_sync_id; | 279 int64 other_bookmarks_sync_id; |
| 280 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_sync_id)) { | 280 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_sync_id)) { |
| 281 return false; | 281 return false; |
| 282 } | 282 } |
| 283 int64 mobile_bookmarks_sync_id; | 283 int64 mobile_bookmarks_sync_id; |
| 284 if (!GetSyncIdForTaggedNode(kMobileBookmarksTag, &mobile_bookmarks_sync_id)) { | 284 if (!GetSyncIdForTaggedNode(kMobileBookmarksTag, &mobile_bookmarks_sync_id)) { |
| 285 has_mobile_folder = false; | 285 has_mobile_folder = false; |
| 286 } | 286 } |
| 287 | 287 |
| 288 csync::ReadTransaction trans(FROM_HERE, user_share_); | 288 syncer::ReadTransaction trans(FROM_HERE, user_share_); |
| 289 | 289 |
| 290 csync::ReadNode bookmark_bar_node(&trans); | 290 syncer::ReadNode bookmark_bar_node(&trans); |
| 291 if (bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id) != | 291 if (bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id) != |
| 292 csync::BaseNode::INIT_OK) { | 292 syncer::BaseNode::INIT_OK) { |
| 293 return false; | 293 return false; |
| 294 } | 294 } |
| 295 | 295 |
| 296 csync::ReadNode other_bookmarks_node(&trans); | 296 syncer::ReadNode other_bookmarks_node(&trans); |
| 297 if (other_bookmarks_node.InitByIdLookup(other_bookmarks_sync_id) != | 297 if (other_bookmarks_node.InitByIdLookup(other_bookmarks_sync_id) != |
| 298 csync::BaseNode::INIT_OK) { | 298 syncer::BaseNode::INIT_OK) { |
| 299 return false; | 299 return false; |
| 300 } | 300 } |
| 301 | 301 |
| 302 csync::ReadNode mobile_bookmarks_node(&trans); | 302 syncer::ReadNode mobile_bookmarks_node(&trans); |
| 303 if (has_mobile_folder && | 303 if (has_mobile_folder && |
| 304 mobile_bookmarks_node.InitByIdLookup(mobile_bookmarks_sync_id) != | 304 mobile_bookmarks_node.InitByIdLookup(mobile_bookmarks_sync_id) != |
| 305 csync::BaseNode::INIT_OK) { | 305 syncer::BaseNode::INIT_OK) { |
| 306 return false; | 306 return false; |
| 307 } | 307 } |
| 308 | 308 |
| 309 // Sync model has user created nodes if any of the permanent nodes has | 309 // Sync model has user created nodes if any of the permanent nodes has |
| 310 // children. | 310 // children. |
| 311 *has_nodes = bookmark_bar_node.HasChildren() || | 311 *has_nodes = bookmark_bar_node.HasChildren() || |
| 312 other_bookmarks_node.HasChildren() || | 312 other_bookmarks_node.HasChildren() || |
| 313 (has_mobile_folder && mobile_bookmarks_node.HasChildren()); | 313 (has_mobile_folder && mobile_bookmarks_node.HasChildren()); |
| 314 return true; | 314 return true; |
| 315 } | 315 } |
| 316 | 316 |
| 317 bool BookmarkModelAssociator::NodesMatch( | 317 bool BookmarkModelAssociator::NodesMatch( |
| 318 const BookmarkNode* bookmark, | 318 const BookmarkNode* bookmark, |
| 319 const csync::BaseNode* sync_node) const { | 319 const syncer::BaseNode* sync_node) const { |
| 320 if (bookmark->GetTitle() != UTF8ToUTF16(sync_node->GetTitle())) | 320 if (bookmark->GetTitle() != UTF8ToUTF16(sync_node->GetTitle())) |
| 321 return false; | 321 return false; |
| 322 if (bookmark->is_folder() != sync_node->GetIsFolder()) | 322 if (bookmark->is_folder() != sync_node->GetIsFolder()) |
| 323 return false; | 323 return false; |
| 324 if (bookmark->is_url()) { | 324 if (bookmark->is_url()) { |
| 325 if (bookmark->url() != sync_node->GetURL()) | 325 if (bookmark->url() != sync_node->GetURL()) |
| 326 return false; | 326 return false; |
| 327 } | 327 } |
| 328 // Don't compare favicons here, because they are not really | 328 // Don't compare favicons here, because they are not really |
| 329 // user-updated and we don't have versioning information -- a site changing | 329 // user-updated and we don't have versioning information -- a site changing |
| 330 // its favicon shouldn't result in a bookmark mismatch. | 330 // its favicon shouldn't result in a bookmark mismatch. |
| 331 return true; | 331 return true; |
| 332 } | 332 } |
| 333 | 333 |
| 334 csync::SyncError BookmarkModelAssociator::AssociateTaggedPermanentNode( | 334 syncer::SyncError BookmarkModelAssociator::AssociateTaggedPermanentNode( |
| 335 const BookmarkNode* permanent_node, const std::string&tag) { | 335 const BookmarkNode* permanent_node, const std::string&tag) { |
| 336 // Do nothing if |permanent_node| is already initialized and associated. | 336 // Do nothing if |permanent_node| is already initialized and associated. |
| 337 int64 sync_id = GetSyncIdFromChromeId(permanent_node->id()); | 337 int64 sync_id = GetSyncIdFromChromeId(permanent_node->id()); |
| 338 if (sync_id != csync::kInvalidId) | 338 if (sync_id != syncer::kInvalidId) |
| 339 return csync::SyncError(); | 339 return syncer::SyncError(); |
| 340 if (!GetSyncIdForTaggedNode(tag, &sync_id)) | 340 if (!GetSyncIdForTaggedNode(tag, &sync_id)) |
| 341 return unrecoverable_error_handler_->CreateAndUploadError( | 341 return unrecoverable_error_handler_->CreateAndUploadError( |
| 342 FROM_HERE, | 342 FROM_HERE, |
| 343 "Permanent node not found", | 343 "Permanent node not found", |
| 344 model_type()); | 344 model_type()); |
| 345 | 345 |
| 346 Associate(permanent_node, sync_id); | 346 Associate(permanent_node, sync_id); |
| 347 return csync::SyncError(); | 347 return syncer::SyncError(); |
| 348 } | 348 } |
| 349 | 349 |
| 350 bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag, | 350 bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag, |
| 351 int64* sync_id) { | 351 int64* sync_id) { |
| 352 csync::ReadTransaction trans(FROM_HERE, user_share_); | 352 syncer::ReadTransaction trans(FROM_HERE, user_share_); |
| 353 csync::ReadNode sync_node(&trans); | 353 syncer::ReadNode sync_node(&trans); |
| 354 if (sync_node.InitByTagLookup(tag.c_str()) != csync::BaseNode::INIT_OK) | 354 if (sync_node.InitByTagLookup(tag.c_str()) != syncer::BaseNode::INIT_OK) |
| 355 return false; | 355 return false; |
| 356 *sync_id = sync_node.GetId(); | 356 *sync_id = sync_node.GetId(); |
| 357 return true; | 357 return true; |
| 358 } | 358 } |
| 359 | 359 |
| 360 csync::SyncError BookmarkModelAssociator::AssociateModels() { | 360 syncer::SyncError BookmarkModelAssociator::AssociateModels() { |
| 361 scoped_ptr<ScopedAssociationUpdater> association_updater( | 361 scoped_ptr<ScopedAssociationUpdater> association_updater( |
| 362 new ScopedAssociationUpdater(bookmark_model_)); | 362 new ScopedAssociationUpdater(bookmark_model_)); |
| 363 // Try to load model associations from persisted associations first. If that | 363 // Try to load model associations from persisted associations first. If that |
| 364 // succeeds, we don't need to run the complex model matching algorithm. | 364 // succeeds, we don't need to run the complex model matching algorithm. |
| 365 if (LoadAssociations()) | 365 if (LoadAssociations()) |
| 366 return csync::SyncError(); | 366 return syncer::SyncError(); |
| 367 | 367 |
| 368 DisassociateModels(); | 368 DisassociateModels(); |
| 369 | 369 |
| 370 // We couldn't load model associations from persisted associations. So build | 370 // We couldn't load model associations from persisted associations. So build |
| 371 // them. | 371 // them. |
| 372 return BuildAssociations(); | 372 return BuildAssociations(); |
| 373 } | 373 } |
| 374 | 374 |
| 375 csync::SyncError BookmarkModelAssociator::BuildAssociations() { | 375 syncer::SyncError BookmarkModelAssociator::BuildAssociations() { |
| 376 // Algorithm description: | 376 // Algorithm description: |
| 377 // Match up the roots and recursively do the following: | 377 // Match up the roots and recursively do the following: |
| 378 // * For each sync node for the current sync parent node, find the best | 378 // * For each sync node for the current sync parent node, find the best |
| 379 // matching bookmark node under the corresponding bookmark parent node. | 379 // matching bookmark node under the corresponding bookmark parent node. |
| 380 // If no matching node is found, create a new bookmark node in the same | 380 // If no matching node is found, create a new bookmark node in the same |
| 381 // position as the corresponding sync node. | 381 // position as the corresponding sync node. |
| 382 // If a matching node is found, update the properties of it from the | 382 // If a matching node is found, update the properties of it from the |
| 383 // corresponding sync node. | 383 // corresponding sync node. |
| 384 // * When all children sync nodes are done, add the extra children bookmark | 384 // * When all children sync nodes are done, add the extra children bookmark |
| 385 // nodes to the sync parent node. | 385 // nodes to the sync parent node. |
| 386 // | 386 // |
| 387 // This algorithm will do a good job of merging when folder names are a good | 387 // This algorithm will do a good job of merging when folder names are a good |
| 388 // indicator of the two folders being the same. It will handle reordering and | 388 // indicator of the two folders being the same. It will handle reordering and |
| 389 // new node addition very well (without creating duplicates). | 389 // new node addition very well (without creating duplicates). |
| 390 // This algorithm will not do well if the folder name has changes but the | 390 // This algorithm will not do well if the folder name has changes but the |
| 391 // children under them are all the same. | 391 // children under them are all the same. |
| 392 | 392 |
| 393 csync::SyncError error; | 393 syncer::SyncError error; |
| 394 DCHECK(bookmark_model_->IsLoaded()); | 394 DCHECK(bookmark_model_->IsLoaded()); |
| 395 | 395 |
| 396 // To prime our association, we associate the top-level nodes, Bookmark Bar | 396 // To prime our association, we associate the top-level nodes, Bookmark Bar |
| 397 // and Other Bookmarks. | 397 // and Other Bookmarks. |
| 398 error = AssociateTaggedPermanentNode(bookmark_model_->other_node(), | 398 error = AssociateTaggedPermanentNode(bookmark_model_->other_node(), |
| 399 kOtherBookmarksTag); | 399 kOtherBookmarksTag); |
| 400 if (error.IsSet()) { | 400 if (error.IsSet()) { |
| 401 return error; | 401 return error; |
| 402 } | 402 } |
| 403 | 403 |
| 404 error = AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(), | 404 error = AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(), |
| 405 kBookmarkBarTag); | 405 kBookmarkBarTag); |
| 406 if (error.IsSet()) { | 406 if (error.IsSet()) { |
| 407 return error; | 407 return error; |
| 408 } | 408 } |
| 409 | 409 |
| 410 if (expect_mobile_bookmarks_folder_) { | 410 if (expect_mobile_bookmarks_folder_) { |
| 411 error = AssociateTaggedPermanentNode(bookmark_model_->mobile_node(), | 411 error = AssociateTaggedPermanentNode(bookmark_model_->mobile_node(), |
| 412 kMobileBookmarksTag); | 412 kMobileBookmarksTag); |
| 413 if (error.IsSet()) { | 413 if (error.IsSet()) { |
| 414 return error; | 414 return error; |
| 415 } | 415 } |
| 416 } | 416 } |
| 417 | 417 |
| 418 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId( | 418 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId( |
| 419 bookmark_model_->bookmark_bar_node()->id()); | 419 bookmark_model_->bookmark_bar_node()->id()); |
| 420 DCHECK_NE(bookmark_bar_sync_id, csync::kInvalidId); | 420 DCHECK_NE(bookmark_bar_sync_id, syncer::kInvalidId); |
| 421 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId( | 421 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId( |
| 422 bookmark_model_->other_node()->id()); | 422 bookmark_model_->other_node()->id()); |
| 423 DCHECK_NE(other_bookmarks_sync_id, csync::kInvalidId); | 423 DCHECK_NE(other_bookmarks_sync_id, syncer::kInvalidId); |
| 424 int64 mobile_bookmarks_sync_id = GetSyncIdFromChromeId( | 424 int64 mobile_bookmarks_sync_id = GetSyncIdFromChromeId( |
| 425 bookmark_model_->mobile_node()->id()); | 425 bookmark_model_->mobile_node()->id()); |
| 426 if (expect_mobile_bookmarks_folder_) { | 426 if (expect_mobile_bookmarks_folder_) { |
| 427 DCHECK_NE(csync::kInvalidId, mobile_bookmarks_sync_id); | 427 DCHECK_NE(syncer::kInvalidId, mobile_bookmarks_sync_id); |
| 428 } | 428 } |
| 429 | 429 |
| 430 std::stack<int64> dfs_stack; | 430 std::stack<int64> dfs_stack; |
| 431 if (mobile_bookmarks_sync_id != csync::kInvalidId) | 431 if (mobile_bookmarks_sync_id != syncer::kInvalidId) |
| 432 dfs_stack.push(mobile_bookmarks_sync_id); | 432 dfs_stack.push(mobile_bookmarks_sync_id); |
| 433 dfs_stack.push(other_bookmarks_sync_id); | 433 dfs_stack.push(other_bookmarks_sync_id); |
| 434 dfs_stack.push(bookmark_bar_sync_id); | 434 dfs_stack.push(bookmark_bar_sync_id); |
| 435 | 435 |
| 436 csync::WriteTransaction trans(FROM_HERE, user_share_); | 436 syncer::WriteTransaction trans(FROM_HERE, user_share_); |
| 437 | 437 |
| 438 while (!dfs_stack.empty()) { | 438 while (!dfs_stack.empty()) { |
| 439 int64 sync_parent_id = dfs_stack.top(); | 439 int64 sync_parent_id = dfs_stack.top(); |
| 440 dfs_stack.pop(); | 440 dfs_stack.pop(); |
| 441 | 441 |
| 442 csync::ReadNode sync_parent(&trans); | 442 syncer::ReadNode sync_parent(&trans); |
| 443 if (sync_parent.InitByIdLookup(sync_parent_id) != | 443 if (sync_parent.InitByIdLookup(sync_parent_id) != |
| 444 csync::BaseNode::INIT_OK) { | 444 syncer::BaseNode::INIT_OK) { |
| 445 return unrecoverable_error_handler_->CreateAndUploadError( | 445 return unrecoverable_error_handler_->CreateAndUploadError( |
| 446 FROM_HERE, | 446 FROM_HERE, |
| 447 "Failed to lookup node.", | 447 "Failed to lookup node.", |
| 448 model_type()); | 448 model_type()); |
| 449 } | 449 } |
| 450 // Only folder nodes are pushed on to the stack. | 450 // Only folder nodes are pushed on to the stack. |
| 451 DCHECK(sync_parent.GetIsFolder()); | 451 DCHECK(sync_parent.GetIsFolder()); |
| 452 | 452 |
| 453 const BookmarkNode* parent_node = GetChromeNodeFromSyncId(sync_parent_id); | 453 const BookmarkNode* parent_node = GetChromeNodeFromSyncId(sync_parent_id); |
| 454 DCHECK(parent_node->is_folder()); | 454 DCHECK(parent_node->is_folder()); |
| 455 | 455 |
| 456 BookmarkNodeFinder node_finder(parent_node); | 456 BookmarkNodeFinder node_finder(parent_node); |
| 457 | 457 |
| 458 int index = 0; | 458 int index = 0; |
| 459 int64 sync_child_id = sync_parent.GetFirstChildId(); | 459 int64 sync_child_id = sync_parent.GetFirstChildId(); |
| 460 while (sync_child_id != csync::kInvalidId) { | 460 while (sync_child_id != syncer::kInvalidId) { |
| 461 csync::WriteNode sync_child_node(&trans); | 461 syncer::WriteNode sync_child_node(&trans); |
| 462 if (sync_child_node.InitByIdLookup(sync_child_id) != | 462 if (sync_child_node.InitByIdLookup(sync_child_id) != |
| 463 csync::BaseNode::INIT_OK) { | 463 syncer::BaseNode::INIT_OK) { |
| 464 return unrecoverable_error_handler_->CreateAndUploadError( | 464 return unrecoverable_error_handler_->CreateAndUploadError( |
| 465 FROM_HERE, | 465 FROM_HERE, |
| 466 "Failed to lookup node.", | 466 "Failed to lookup node.", |
| 467 model_type()); | 467 model_type()); |
| 468 } | 468 } |
| 469 | 469 |
| 470 const BookmarkNode* child_node = NULL; | 470 const BookmarkNode* child_node = NULL; |
| 471 child_node = node_finder.FindBookmarkNode(sync_child_node); | 471 child_node = node_finder.FindBookmarkNode(sync_child_node); |
| 472 if (child_node) { | 472 if (child_node) { |
| 473 bookmark_model_->Move(child_node, parent_node, index); | 473 bookmark_model_->Move(child_node, parent_node, index); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 502 | 502 |
| 503 // At this point all the children nodes of the parent sync node have | 503 // At this point all the children nodes of the parent sync node have |
| 504 // corresponding children in the parent bookmark node and they are all in | 504 // corresponding children in the parent bookmark node and they are all in |
| 505 // the right positions: from 0 to index - 1. | 505 // the right positions: from 0 to index - 1. |
| 506 // So the children starting from index in the parent bookmark node are the | 506 // So the children starting from index in the parent bookmark node are the |
| 507 // ones that are not present in the parent sync node. So create them. | 507 // ones that are not present in the parent sync node. So create them. |
| 508 for (int i = index; i < parent_node->child_count(); ++i) { | 508 for (int i = index; i < parent_node->child_count(); ++i) { |
| 509 sync_child_id = BookmarkChangeProcessor::CreateSyncNode( | 509 sync_child_id = BookmarkChangeProcessor::CreateSyncNode( |
| 510 parent_node, bookmark_model_, i, &trans, this, | 510 parent_node, bookmark_model_, i, &trans, this, |
| 511 unrecoverable_error_handler_); | 511 unrecoverable_error_handler_); |
| 512 if (csync::kInvalidId == sync_child_id) { | 512 if (syncer::kInvalidId == sync_child_id) { |
| 513 return unrecoverable_error_handler_->CreateAndUploadError( | 513 return unrecoverable_error_handler_->CreateAndUploadError( |
| 514 FROM_HERE, | 514 FROM_HERE, |
| 515 "Failed to create sync node.", | 515 "Failed to create sync node.", |
| 516 model_type()); | 516 model_type()); |
| 517 } | 517 } |
| 518 if (parent_node->GetChild(i)->is_folder()) | 518 if (parent_node->GetChild(i)->is_folder()) |
| 519 dfs_stack.push(sync_child_id); | 519 dfs_stack.push(sync_child_id); |
| 520 number_of_new_sync_nodes_created_at_association_++; | 520 number_of_new_sync_nodes_created_at_association_++; |
| 521 } | 521 } |
| 522 } | 522 } |
| 523 | 523 |
| 524 return csync::SyncError(); | 524 return syncer::SyncError(); |
| 525 } | 525 } |
| 526 | 526 |
| 527 void BookmarkModelAssociator::PostPersistAssociationsTask() { | 527 void BookmarkModelAssociator::PostPersistAssociationsTask() { |
| 528 // No need to post a task if a task is already pending. | 528 // No need to post a task if a task is already pending. |
| 529 if (weak_factory_.HasWeakPtrs()) | 529 if (weak_factory_.HasWeakPtrs()) |
| 530 return; | 530 return; |
| 531 MessageLoop::current()->PostTask( | 531 MessageLoop::current()->PostTask( |
| 532 FROM_HERE, | 532 FROM_HERE, |
| 533 base::Bind( | 533 base::Bind( |
| 534 &BookmarkModelAssociator::PersistAssociations, | 534 &BookmarkModelAssociator::PersistAssociations, |
| 535 weak_factory_.GetWeakPtr())); | 535 weak_factory_.GetWeakPtr())); |
| 536 } | 536 } |
| 537 | 537 |
| 538 void BookmarkModelAssociator::PersistAssociations() { | 538 void BookmarkModelAssociator::PersistAssociations() { |
| 539 // If there are no dirty associations we have nothing to do. We handle this | 539 // If there are no dirty associations we have nothing to do. We handle this |
| 540 // explicity instead of letting the for loop do it to avoid creating a write | 540 // explicity instead of letting the for loop do it to avoid creating a write |
| 541 // transaction in this case. | 541 // transaction in this case. |
| 542 if (dirty_associations_sync_ids_.empty()) { | 542 if (dirty_associations_sync_ids_.empty()) { |
| 543 DCHECK(id_map_.empty()); | 543 DCHECK(id_map_.empty()); |
| 544 DCHECK(id_map_inverse_.empty()); | 544 DCHECK(id_map_inverse_.empty()); |
| 545 return; | 545 return; |
| 546 } | 546 } |
| 547 | 547 |
| 548 csync::WriteTransaction trans(FROM_HERE, user_share_); | 548 syncer::WriteTransaction trans(FROM_HERE, user_share_); |
| 549 DirtyAssociationsSyncIds::iterator iter; | 549 DirtyAssociationsSyncIds::iterator iter; |
| 550 for (iter = dirty_associations_sync_ids_.begin(); | 550 for (iter = dirty_associations_sync_ids_.begin(); |
| 551 iter != dirty_associations_sync_ids_.end(); | 551 iter != dirty_associations_sync_ids_.end(); |
| 552 ++iter) { | 552 ++iter) { |
| 553 int64 sync_id = *iter; | 553 int64 sync_id = *iter; |
| 554 csync::WriteNode sync_node(&trans); | 554 syncer::WriteNode sync_node(&trans); |
| 555 if (sync_node.InitByIdLookup(sync_id) != csync::BaseNode::INIT_OK) { | 555 if (sync_node.InitByIdLookup(sync_id) != syncer::BaseNode::INIT_OK) { |
| 556 unrecoverable_error_handler_->OnSingleDatatypeUnrecoverableError( | 556 unrecoverable_error_handler_->OnSingleDatatypeUnrecoverableError( |
| 557 FROM_HERE, | 557 FROM_HERE, |
| 558 "Could not lookup bookmark node for ID persistence."); | 558 "Could not lookup bookmark node for ID persistence."); |
| 559 return; | 559 return; |
| 560 } | 560 } |
| 561 const BookmarkNode* node = GetChromeNodeFromSyncId(sync_id); | 561 const BookmarkNode* node = GetChromeNodeFromSyncId(sync_id); |
| 562 if (node) | 562 if (node) |
| 563 sync_node.SetExternalId(node->id()); | 563 sync_node.SetExternalId(node->id()); |
| 564 else | 564 else |
| 565 NOTREACHED(); | 565 NOTREACHED(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 id_index.AddAll(bookmark_model_->bookmark_bar_node()); | 600 id_index.AddAll(bookmark_model_->bookmark_bar_node()); |
| 601 id_index.AddAll(bookmark_model_->other_node()); | 601 id_index.AddAll(bookmark_model_->other_node()); |
| 602 id_index.AddAll(bookmark_model_->mobile_node()); | 602 id_index.AddAll(bookmark_model_->mobile_node()); |
| 603 | 603 |
| 604 std::stack<int64> dfs_stack; | 604 std::stack<int64> dfs_stack; |
| 605 if (mobile_bookmarks_id != -1) | 605 if (mobile_bookmarks_id != -1) |
| 606 dfs_stack.push(mobile_bookmarks_id); | 606 dfs_stack.push(mobile_bookmarks_id); |
| 607 dfs_stack.push(other_bookmarks_id); | 607 dfs_stack.push(other_bookmarks_id); |
| 608 dfs_stack.push(bookmark_bar_id); | 608 dfs_stack.push(bookmark_bar_id); |
| 609 | 609 |
| 610 csync::ReadTransaction trans(FROM_HERE, user_share_); | 610 syncer::ReadTransaction trans(FROM_HERE, user_share_); |
| 611 | 611 |
| 612 // Count total number of nodes in sync model so that we can compare that | 612 // Count total number of nodes in sync model so that we can compare that |
| 613 // with the total number of nodes in the bookmark model. | 613 // with the total number of nodes in the bookmark model. |
| 614 size_t sync_node_count = 0; | 614 size_t sync_node_count = 0; |
| 615 while (!dfs_stack.empty()) { | 615 while (!dfs_stack.empty()) { |
| 616 int64 parent_id = dfs_stack.top(); | 616 int64 parent_id = dfs_stack.top(); |
| 617 dfs_stack.pop(); | 617 dfs_stack.pop(); |
| 618 ++sync_node_count; | 618 ++sync_node_count; |
| 619 csync::ReadNode sync_parent(&trans); | 619 syncer::ReadNode sync_parent(&trans); |
| 620 if (sync_parent.InitByIdLookup(parent_id) != csync::BaseNode::INIT_OK) { | 620 if (sync_parent.InitByIdLookup(parent_id) != syncer::BaseNode::INIT_OK) { |
| 621 return false; | 621 return false; |
| 622 } | 622 } |
| 623 | 623 |
| 624 int64 external_id = sync_parent.GetExternalId(); | 624 int64 external_id = sync_parent.GetExternalId(); |
| 625 if (external_id == 0) | 625 if (external_id == 0) |
| 626 return false; | 626 return false; |
| 627 | 627 |
| 628 const BookmarkNode* node = id_index.Find(external_id); | 628 const BookmarkNode* node = id_index.Find(external_id); |
| 629 if (!node) | 629 if (!node) |
| 630 return false; | 630 return false; |
| 631 | 631 |
| 632 // Don't try to call NodesMatch on permanent nodes like bookmark bar and | 632 // Don't try to call NodesMatch on permanent nodes like bookmark bar and |
| 633 // other bookmarks. They are not expected to match. | 633 // other bookmarks. They are not expected to match. |
| 634 if (node != bookmark_model_->bookmark_bar_node() && | 634 if (node != bookmark_model_->bookmark_bar_node() && |
| 635 node != bookmark_model_->mobile_node() && | 635 node != bookmark_model_->mobile_node() && |
| 636 node != bookmark_model_->other_node() && | 636 node != bookmark_model_->other_node() && |
| 637 !NodesMatch(node, &sync_parent)) | 637 !NodesMatch(node, &sync_parent)) |
| 638 return false; | 638 return false; |
| 639 | 639 |
| 640 Associate(node, sync_parent.GetId()); | 640 Associate(node, sync_parent.GetId()); |
| 641 | 641 |
| 642 // Add all children of the current node to the stack. | 642 // Add all children of the current node to the stack. |
| 643 int64 child_id = sync_parent.GetFirstChildId(); | 643 int64 child_id = sync_parent.GetFirstChildId(); |
| 644 while (child_id != csync::kInvalidId) { | 644 while (child_id != syncer::kInvalidId) { |
| 645 dfs_stack.push(child_id); | 645 dfs_stack.push(child_id); |
| 646 csync::ReadNode child_node(&trans); | 646 syncer::ReadNode child_node(&trans); |
| 647 if (child_node.InitByIdLookup(child_id) != csync::BaseNode::INIT_OK) { | 647 if (child_node.InitByIdLookup(child_id) != syncer::BaseNode::INIT_OK) { |
| 648 return false; | 648 return false; |
| 649 } | 649 } |
| 650 child_id = child_node.GetSuccessorId(); | 650 child_id = child_node.GetSuccessorId(); |
| 651 } | 651 } |
| 652 } | 652 } |
| 653 DCHECK(dfs_stack.empty()); | 653 DCHECK(dfs_stack.empty()); |
| 654 | 654 |
| 655 // It's possible that the number of nodes in the bookmark model is not the | 655 // It's possible that the number of nodes in the bookmark model is not the |
| 656 // same as number of nodes in the sync model. This can happen when the sync | 656 // same as number of nodes in the sync model. This can happen when the sync |
| 657 // model doesn't get a chance to persist its changes, for example when | 657 // model doesn't get a chance to persist its changes, for example when |
| 658 // Chrome does not shut down gracefully. In such cases we can't trust the | 658 // Chrome does not shut down gracefully. In such cases we can't trust the |
| 659 // loaded associations. | 659 // loaded associations. |
| 660 return sync_node_count == id_index.count(); | 660 return sync_node_count == id_index.count(); |
| 661 } | 661 } |
| 662 | 662 |
| 663 bool BookmarkModelAssociator::CryptoReadyIfNecessary() { | 663 bool BookmarkModelAssociator::CryptoReadyIfNecessary() { |
| 664 // We only access the cryptographer while holding a transaction. | 664 // We only access the cryptographer while holding a transaction. |
| 665 csync::ReadTransaction trans(FROM_HERE, user_share_); | 665 syncer::ReadTransaction trans(FROM_HERE, user_share_); |
| 666 const syncable::ModelTypeSet encrypted_types = | 666 const syncable::ModelTypeSet encrypted_types = |
| 667 csync::GetEncryptedTypes(&trans); | 667 syncer::GetEncryptedTypes(&trans); |
| 668 return !encrypted_types.Has(syncable::BOOKMARKS) || | 668 return !encrypted_types.Has(syncable::BOOKMARKS) || |
| 669 trans.GetCryptographer()->is_ready(); | 669 trans.GetCryptographer()->is_ready(); |
| 670 } | 670 } |
| 671 | 671 |
| 672 } // namespace browser_sync | 672 } // namespace browser_sync |
| OLD | NEW |