| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 #if defined(BROWSER_SYNC) | 5 #if defined(BROWSER_SYNC) |
| 6 | 6 |
| 7 #include "chrome/browser/sync/glue/model_associator.h" | 7 #include "chrome/browser/sync/glue/model_associator.h" |
| 8 | 8 |
| 9 #include <stack> | 9 #include <stack> |
| 10 | 10 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 | 114 |
| 115 ModelAssociator::ModelAssociator(ProfileSyncService* sync_service) | 115 ModelAssociator::ModelAssociator(ProfileSyncService* sync_service) |
| 116 : sync_service_(sync_service), | 116 : sync_service_(sync_service), |
| 117 task_pending_(false) { | 117 task_pending_(false) { |
| 118 DCHECK(sync_service_); | 118 DCHECK(sync_service_); |
| 119 } | 119 } |
| 120 | 120 |
| 121 void ModelAssociator::ClearAll() { | 121 void ModelAssociator::ClearAll() { |
| 122 id_map_.clear(); | 122 id_map_.clear(); |
| 123 id_map_inverse_.clear(); | 123 id_map_inverse_.clear(); |
| 124 dirty_assocations_sync_ids_.clear(); | 124 dirty_associations_sync_ids_.clear(); |
| 125 } | 125 } |
| 126 | 126 |
| 127 int64 ModelAssociator::GetSyncIdFromBookmarkId(int64 node_id) const { | 127 int64 ModelAssociator::GetSyncIdFromBookmarkId(int64 node_id) const { |
| 128 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id); | 128 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id); |
| 129 return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; | 129 return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; |
| 130 } | 130 } |
| 131 | 131 |
| 132 bool ModelAssociator::GetBookmarkIdFromSyncId(int64 sync_id, | 132 bool ModelAssociator::GetBookmarkIdFromSyncId(int64 sync_id, |
| 133 int64* node_id) const { | 133 int64* node_id) const { |
| 134 SyncIdToBookmarkIdMap::const_iterator iter = id_map_inverse_.find(sync_id); | 134 SyncIdToBookmarkIdMap::const_iterator iter = id_map_inverse_.find(sync_id); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 158 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); | 158 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); |
| 159 return model->GetNodeByID(node_id); | 159 return model->GetNodeByID(node_id); |
| 160 } | 160 } |
| 161 | 161 |
| 162 void ModelAssociator::AssociateIds(int64 node_id, int64 sync_id) { | 162 void ModelAssociator::AssociateIds(int64 node_id, int64 sync_id) { |
| 163 DCHECK_NE(sync_id, sync_api::kInvalidId); | 163 DCHECK_NE(sync_id, sync_api::kInvalidId); |
| 164 DCHECK(id_map_.find(node_id) == id_map_.end()); | 164 DCHECK(id_map_.find(node_id) == id_map_.end()); |
| 165 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); | 165 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); |
| 166 id_map_[node_id] = sync_id; | 166 id_map_[node_id] = sync_id; |
| 167 id_map_inverse_[sync_id] = node_id; | 167 id_map_inverse_[sync_id] = node_id; |
| 168 dirty_assocations_sync_ids_.insert(sync_id); | 168 dirty_associations_sync_ids_.insert(sync_id); |
| 169 PostPersistAssociationsTask(); | 169 PostPersistAssociationsTask(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 void ModelAssociator::DisassociateIds(int64 sync_id) { | 172 void ModelAssociator::DisassociateIds(int64 sync_id) { |
| 173 SyncIdToBookmarkIdMap::iterator iter = id_map_inverse_.find(sync_id); | 173 SyncIdToBookmarkIdMap::iterator iter = id_map_inverse_.find(sync_id); |
| 174 if (iter == id_map_inverse_.end()) | 174 if (iter == id_map_inverse_.end()) |
| 175 return; | 175 return; |
| 176 id_map_.erase(iter->second); | 176 id_map_.erase(iter->second); |
| 177 id_map_inverse_.erase(iter); | 177 id_map_inverse_.erase(iter); |
| 178 dirty_assocations_sync_ids_.erase(sync_id); | 178 dirty_associations_sync_ids_.erase(sync_id); |
| 179 } | 179 } |
| 180 | 180 |
| 181 bool ModelAssociator::BookmarkModelHasUserCreatedNodes() const { | 181 bool ModelAssociator::BookmarkModelHasUserCreatedNodes() const { |
| 182 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); | 182 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); |
| 183 DCHECK(model->IsLoaded()); | 183 DCHECK(model->IsLoaded()); |
| 184 return model->GetBookmarkBarNode()->GetChildCount() > 0 || | 184 return model->GetBookmarkBarNode()->GetChildCount() > 0 || |
| 185 model->other_node()->GetChildCount() > 0; | 185 model->other_node()->GetChildCount() > 0; |
| 186 } | 186 } |
| 187 | 187 |
| 188 bool ModelAssociator::SyncModelHasUserCreatedNodes() { | 188 bool ModelAssociator::SyncModelHasUserCreatedNodes() { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 262 } |
| 263 | 263 |
| 264 bool ModelAssociator::AssociateModels() { | 264 bool ModelAssociator::AssociateModels() { |
| 265 // Try to load model associations from persisted associations first. If that | 265 // Try to load model associations from persisted associations first. If that |
| 266 // succeeds, we don't need to run the complex model matching algorithm. | 266 // succeeds, we don't need to run the complex model matching algorithm. |
| 267 if (LoadAssociations()) | 267 if (LoadAssociations()) |
| 268 return true; | 268 return true; |
| 269 | 269 |
| 270 ClearAll(); | 270 ClearAll(); |
| 271 | 271 |
| 272 // We couldn't load model assocations from persisted assocations. So build | 272 // We couldn't load model associations from persisted associations. So build |
| 273 // them. | 273 // them. |
| 274 return BuildAssocations(); | 274 return BuildAssociations(); |
| 275 } | 275 } |
| 276 | 276 |
| 277 bool ModelAssociator::BuildAssocations() { | 277 bool ModelAssociator::BuildAssociations() { |
| 278 // Algorithm description: | 278 // Algorithm description: |
| 279 // Match up the roots and recursively do the following: | 279 // Match up the roots and recursively do the following: |
| 280 // * For each sync node for the current sync parent node, find the best | 280 // * For each sync node for the current sync parent node, find the best |
| 281 // matching bookmark node under the corresponding bookmark parent node. | 281 // matching bookmark node under the corresponding bookmark parent node. |
| 282 // If no matching node is found, create a new bookmark node in the same | 282 // If no matching node is found, create a new bookmark node in the same |
| 283 // position as the corresponding sync node. | 283 // position as the corresponding sync node. |
| 284 // If a matching node is found, update the properties of it from the | 284 // If a matching node is found, update the properties of it from the |
| 285 // corresponding sync node. | 285 // corresponding sync node. |
| 286 // * When all children sync nodes are done, add the extra children bookmark | 286 // * When all children sync nodes are done, add the extra children bookmark |
| 287 // nodes to the sync parent node. | 287 // nodes to the sync parent node. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 task_pending_ = true; | 396 task_pending_ = true; |
| 397 MessageLoop::current()->PostTask( | 397 MessageLoop::current()->PostTask( |
| 398 FROM_HERE, | 398 FROM_HERE, |
| 399 NewRunnableMethod(this, &ModelAssociator::PersistAssociations)); | 399 NewRunnableMethod(this, &ModelAssociator::PersistAssociations)); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void ModelAssociator::PersistAssociations() { | 402 void ModelAssociator::PersistAssociations() { |
| 403 DCHECK(task_pending_); | 403 DCHECK(task_pending_); |
| 404 task_pending_ = false; | 404 task_pending_ = false; |
| 405 | 405 |
| 406 // If there are no dirty assocations we have nothing to do. We handle this | 406 // If there are no dirty associations we have nothing to do. We handle this |
| 407 // explicity instead of letting the for loop do it to avoid creating a write | 407 // explicity instead of letting the for loop do it to avoid creating a write |
| 408 // transaction in this case. | 408 // transaction in this case. |
| 409 if (dirty_assocations_sync_ids_.empty()) { | 409 if (dirty_associations_sync_ids_.empty()) { |
| 410 DCHECK(id_map_.empty()); | 410 DCHECK(id_map_.empty()); |
| 411 DCHECK(id_map_inverse_.empty()); | 411 DCHECK(id_map_inverse_.empty()); |
| 412 return; | 412 return; |
| 413 } | 413 } |
| 414 | 414 |
| 415 sync_api::WriteTransaction trans( | 415 sync_api::WriteTransaction trans( |
| 416 sync_service_->backend()->GetUserShareHandle()); | 416 sync_service_->backend()->GetUserShareHandle()); |
| 417 DirtyAssocationsSyncIds::iterator iter; | 417 DirtyAssociationsSyncIds::iterator iter; |
| 418 for (iter = dirty_assocations_sync_ids_.begin(); | 418 for (iter = dirty_associations_sync_ids_.begin(); |
| 419 iter != dirty_assocations_sync_ids_.end(); | 419 iter != dirty_associations_sync_ids_.end(); |
| 420 ++iter) { | 420 ++iter) { |
| 421 int64 sync_id = *iter; | 421 int64 sync_id = *iter; |
| 422 sync_api::WriteNode sync_node(&trans); | 422 sync_api::WriteNode sync_node(&trans); |
| 423 if (!sync_node.InitByIdLookup(sync_id)) { | 423 if (!sync_node.InitByIdLookup(sync_id)) { |
| 424 sync_service_->OnUnrecoverableError(); | 424 sync_service_->OnUnrecoverableError(); |
| 425 return; | 425 return; |
| 426 } | 426 } |
| 427 int64 node_id; | 427 int64 node_id; |
| 428 if (GetBookmarkIdFromSyncId(sync_id, &node_id)) | 428 if (GetBookmarkIdFromSyncId(sync_id, &node_id)) |
| 429 sync_node.SetExternalId(node_id); | 429 sync_node.SetExternalId(node_id); |
| 430 else | 430 else |
| 431 NOTREACHED(); | 431 NOTREACHED(); |
| 432 } | 432 } |
| 433 dirty_assocations_sync_ids_.clear(); | 433 dirty_associations_sync_ids_.clear(); |
| 434 } | 434 } |
| 435 | 435 |
| 436 bool ModelAssociator::LoadAssociations() { | 436 bool ModelAssociator::LoadAssociations() { |
| 437 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); | 437 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); |
| 438 DCHECK(model->IsLoaded()); | 438 DCHECK(model->IsLoaded()); |
| 439 // If the bookmarks changed externally, our previous assocations may not be | 439 // If the bookmarks changed externally, our previous associations may not be |
| 440 // valid; so return false. | 440 // valid; so return false. |
| 441 if (model->file_changed()) | 441 if (model->file_changed()) |
| 442 return false; | 442 return false; |
| 443 | 443 |
| 444 // Our persisted assocations should be valid. Try to populate id assocation | 444 // Our persisted associations should be valid. Try to populate id association |
| 445 // maps using persisted assocations. | 445 // maps using persisted associations. |
| 446 | |
| 447 int64 other_bookmarks_id; | |
| 448 if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag), | |
| 449 &other_bookmarks_id)) { | |
| 450 // We should always be able to find the permanent nodes. | |
| 451 sync_service_->OnUnrecoverableError(); | |
| 452 return false; | |
| 453 } | |
| 454 int64 bookmark_bar_id; | 446 int64 bookmark_bar_id; |
| 455 if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag), &bookmark_bar_id)) { | 447 if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag), &bookmark_bar_id)) { |
| 456 // We should always be able to find the permanent nodes. | 448 // We should always be able to find the permanent nodes. |
| 457 sync_service_->OnUnrecoverableError(); | 449 sync_service_->OnUnrecoverableError(); |
| 458 return false; | 450 return false; |
| 459 } | 451 } |
| 452 int64 other_bookmarks_id; |
| 453 if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag), |
| 454 &other_bookmarks_id)) { |
| 455 // We should always be able to find the permanent nodes. |
| 456 sync_service_->OnUnrecoverableError(); |
| 457 return false; |
| 458 } |
| 460 | 459 |
| 461 std::stack<int64> dfs_stack; | 460 std::stack<int64> dfs_stack; |
| 462 dfs_stack.push(other_bookmarks_id); | 461 dfs_stack.push(other_bookmarks_id); |
| 463 dfs_stack.push(bookmark_bar_id); | 462 dfs_stack.push(bookmark_bar_id); |
| 464 | 463 |
| 465 sync_api::ReadTransaction trans( | 464 sync_api::ReadTransaction trans( |
| 466 sync_service_->backend()->GetUserShareHandle()); | 465 sync_service_->backend()->GetUserShareHandle()); |
| 467 | 466 |
| 468 while (!dfs_stack.empty()) { | 467 while (!dfs_stack.empty()) { |
| 469 int64 parent_id = dfs_stack.top(); | 468 int64 parent_id = dfs_stack.top(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 child_id = child_node.GetSuccessorId(); | 502 child_id = child_node.GetSuccessorId(); |
| 504 } | 503 } |
| 505 } | 504 } |
| 506 DCHECK(dfs_stack.empty()); | 505 DCHECK(dfs_stack.empty()); |
| 507 return true; | 506 return true; |
| 508 } | 507 } |
| 509 | 508 |
| 510 } // namespace browser_sync | 509 } // namespace browser_sync |
| 511 | 510 |
| 512 #endif // defined(BROWSER_SYNC) | 511 #endif // defined(BROWSER_SYNC) |
| OLD | NEW |