| 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_change_processor.h" | 5 #include "chrome/browser/sync/glue/bookmark_change_processor.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 void BookmarkChangeProcessor::StopImpl() { | 52 void BookmarkChangeProcessor::StopImpl() { |
| 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 54 DCHECK(bookmark_model_); | 54 DCHECK(bookmark_model_); |
| 55 bookmark_model_->RemoveObserver(this); | 55 bookmark_model_->RemoveObserver(this); |
| 56 bookmark_model_ = NULL; | 56 bookmark_model_ = NULL; |
| 57 model_associator_ = NULL; | 57 model_associator_ = NULL; |
| 58 } | 58 } |
| 59 | 59 |
| 60 void BookmarkChangeProcessor::UpdateSyncNodeProperties( | 60 void BookmarkChangeProcessor::UpdateSyncNodeProperties( |
| 61 const BookmarkNode* src, BookmarkModel* model, csync::WriteNode* dst) { | 61 const BookmarkNode* src, BookmarkModel* model, syncer::WriteNode* dst) { |
| 62 // Set the properties of the item. | 62 // Set the properties of the item. |
| 63 dst->SetIsFolder(src->is_folder()); | 63 dst->SetIsFolder(src->is_folder()); |
| 64 dst->SetTitle(UTF16ToWideHack(src->GetTitle())); | 64 dst->SetTitle(UTF16ToWideHack(src->GetTitle())); |
| 65 if (!src->is_folder()) | 65 if (!src->is_folder()) |
| 66 dst->SetURL(src->url()); | 66 dst->SetURL(src->url()); |
| 67 SetSyncNodeFavicon(src, model, dst); | 67 SetSyncNodeFavicon(src, model, dst); |
| 68 } | 68 } |
| 69 | 69 |
| 70 // static | 70 // static |
| 71 void BookmarkChangeProcessor::EncodeFavicon(const BookmarkNode* src, | 71 void BookmarkChangeProcessor::EncodeFavicon(const BookmarkNode* src, |
| 72 BookmarkModel* model, | 72 BookmarkModel* model, |
| 73 std::vector<unsigned char>* dst) { | 73 std::vector<unsigned char>* dst) { |
| 74 const gfx::Image& favicon = model->GetFavicon(src); | 74 const gfx::Image& favicon = model->GetFavicon(src); |
| 75 | 75 |
| 76 dst->clear(); | 76 dst->clear(); |
| 77 | 77 |
| 78 // Check for empty images. This can happen if the favicon is | 78 // Check for empty images. This can happen if the favicon is |
| 79 // still being loaded. | 79 // still being loaded. |
| 80 if (favicon.IsEmpty()) | 80 if (favicon.IsEmpty()) |
| 81 return; | 81 return; |
| 82 | 82 |
| 83 // Re-encode the BookmarkNode's favicon as a PNG, and pass the data to the | 83 // Re-encode the BookmarkNode's favicon as a PNG, and pass the data to the |
| 84 // sync subsystem. | 84 // sync subsystem. |
| 85 if (!gfx::PNGEncodedDataFromImage(favicon, dst)) | 85 if (!gfx::PNGEncodedDataFromImage(favicon, dst)) |
| 86 return; | 86 return; |
| 87 } | 87 } |
| 88 | 88 |
| 89 void BookmarkChangeProcessor::RemoveOneSyncNode( | 89 void BookmarkChangeProcessor::RemoveOneSyncNode( |
| 90 csync::WriteTransaction* trans, const BookmarkNode* node) { | 90 syncer::WriteTransaction* trans, const BookmarkNode* node) { |
| 91 csync::WriteNode sync_node(trans); | 91 syncer::WriteNode sync_node(trans); |
| 92 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { | 92 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { |
| 93 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 93 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 94 std::string()); | 94 std::string()); |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 // This node should have no children. | 97 // This node should have no children. |
| 98 DCHECK(!sync_node.HasChildren()); | 98 DCHECK(!sync_node.HasChildren()); |
| 99 // Remove association and delete the sync node. | 99 // Remove association and delete the sync node. |
| 100 model_associator_->Disassociate(sync_node.GetId()); | 100 model_associator_->Disassociate(sync_node.GetId()); |
| 101 sync_node.Remove(); | 101 sync_node.Remove(); |
| 102 } | 102 } |
| 103 | 103 |
| 104 void BookmarkChangeProcessor::RemoveSyncNodeHierarchy( | 104 void BookmarkChangeProcessor::RemoveSyncNodeHierarchy( |
| 105 const BookmarkNode* topmost) { | 105 const BookmarkNode* topmost) { |
| 106 csync::WriteTransaction trans(FROM_HERE, share_handle()); | 106 syncer::WriteTransaction trans(FROM_HERE, share_handle()); |
| 107 | 107 |
| 108 // Later logic assumes that |topmost| has been unlinked. | 108 // Later logic assumes that |topmost| has been unlinked. |
| 109 DCHECK(topmost->is_root()); | 109 DCHECK(topmost->is_root()); |
| 110 | 110 |
| 111 // A BookmarkModel deletion event means that |node| and all its children were | 111 // A BookmarkModel deletion event means that |node| and all its children were |
| 112 // deleted. Sync backend expects children to be deleted individually, so we do | 112 // deleted. Sync backend expects children to be deleted individually, so we do |
| 113 // a depth-first-search here. At each step, we consider the |index|-th child | 113 // a depth-first-search here. At each step, we consider the |index|-th child |
| 114 // of |node|. |index_stack| stores index values for the parent levels. | 114 // of |node|. |index_stack| stores index values for the parent levels. |
| 115 std::stack<int> index_stack; | 115 std::stack<int> index_stack; |
| 116 index_stack.push(0); // For the final pop. It's never used. | 116 index_stack.push(0); // For the final pop. It's never used. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 bookmark_model_ = NULL; | 150 bookmark_model_ = NULL; |
| 151 } | 151 } |
| 152 | 152 |
| 153 void BookmarkChangeProcessor::BookmarkNodeAdded(BookmarkModel* model, | 153 void BookmarkChangeProcessor::BookmarkNodeAdded(BookmarkModel* model, |
| 154 const BookmarkNode* parent, | 154 const BookmarkNode* parent, |
| 155 int index) { | 155 int index) { |
| 156 DCHECK(running()); | 156 DCHECK(running()); |
| 157 DCHECK(share_handle()); | 157 DCHECK(share_handle()); |
| 158 | 158 |
| 159 // Acquire a scoped write lock via a transaction. | 159 // Acquire a scoped write lock via a transaction. |
| 160 csync::WriteTransaction trans(FROM_HERE, share_handle()); | 160 syncer::WriteTransaction trans(FROM_HERE, share_handle()); |
| 161 | 161 |
| 162 CreateSyncNode(parent, model, index, &trans, model_associator_, | 162 CreateSyncNode(parent, model, index, &trans, model_associator_, |
| 163 error_handler()); | 163 error_handler()); |
| 164 } | 164 } |
| 165 | 165 |
| 166 // static | 166 // static |
| 167 int64 BookmarkChangeProcessor::CreateSyncNode(const BookmarkNode* parent, | 167 int64 BookmarkChangeProcessor::CreateSyncNode(const BookmarkNode* parent, |
| 168 BookmarkModel* model, int index, csync::WriteTransaction* trans, | 168 BookmarkModel* model, int index, syncer::WriteTransaction* trans, |
| 169 BookmarkModelAssociator* associator, | 169 BookmarkModelAssociator* associator, |
| 170 DataTypeErrorHandler* error_handler) { | 170 DataTypeErrorHandler* error_handler) { |
| 171 const BookmarkNode* child = parent->GetChild(index); | 171 const BookmarkNode* child = parent->GetChild(index); |
| 172 DCHECK(child); | 172 DCHECK(child); |
| 173 | 173 |
| 174 // Create a WriteNode container to hold the new node. | 174 // Create a WriteNode container to hold the new node. |
| 175 csync::WriteNode sync_child(trans); | 175 syncer::WriteNode sync_child(trans); |
| 176 | 176 |
| 177 // Actually create the node with the appropriate initial position. | 177 // Actually create the node with the appropriate initial position. |
| 178 if (!PlaceSyncNode(CREATE, parent, index, trans, &sync_child, associator)) { | 178 if (!PlaceSyncNode(CREATE, parent, index, trans, &sync_child, associator)) { |
| 179 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 179 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 180 "Sync node creation failed; recovery unlikely"); | 180 "Sync node creation failed; recovery unlikely"); |
| 181 return csync::kInvalidId; | 181 return syncer::kInvalidId; |
| 182 } | 182 } |
| 183 | 183 |
| 184 UpdateSyncNodeProperties(child, model, &sync_child); | 184 UpdateSyncNodeProperties(child, model, &sync_child); |
| 185 | 185 |
| 186 // Associate the ID from the sync domain with the bookmark node, so that we | 186 // Associate the ID from the sync domain with the bookmark node, so that we |
| 187 // can refer back to this item later. | 187 // can refer back to this item later. |
| 188 associator->Associate(child, sync_child.GetId()); | 188 associator->Associate(child, sync_child.GetId()); |
| 189 | 189 |
| 190 return sync_child.GetId(); | 190 return sync_child.GetId(); |
| 191 } | 191 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 202 void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model, | 202 void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model, |
| 203 const BookmarkNode* node) { | 203 const BookmarkNode* node) { |
| 204 DCHECK(running()); | 204 DCHECK(running()); |
| 205 // We shouldn't see changes to the top-level nodes. | 205 // We shouldn't see changes to the top-level nodes. |
| 206 if (model->is_permanent_node(node)) { | 206 if (model->is_permanent_node(node)) { |
| 207 NOTREACHED() << "Saw update to permanent node!"; | 207 NOTREACHED() << "Saw update to permanent node!"; |
| 208 return; | 208 return; |
| 209 } | 209 } |
| 210 | 210 |
| 211 // Acquire a scoped write lock via a transaction. | 211 // Acquire a scoped write lock via a transaction. |
| 212 csync::WriteTransaction trans(FROM_HERE, share_handle()); | 212 syncer::WriteTransaction trans(FROM_HERE, share_handle()); |
| 213 | 213 |
| 214 // Lookup the sync node that's associated with |node|. | 214 // Lookup the sync node that's associated with |node|. |
| 215 csync::WriteNode sync_node(&trans); | 215 syncer::WriteNode sync_node(&trans); |
| 216 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { | 216 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { |
| 217 // TODO(tim): Investigating bug 121587. | 217 // TODO(tim): Investigating bug 121587. |
| 218 if (model_associator_->GetSyncIdFromChromeId(node->id()) == | 218 if (model_associator_->GetSyncIdFromChromeId(node->id()) == |
| 219 csync::kInvalidId) { | 219 syncer::kInvalidId) { |
| 220 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 220 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 221 "Bookmark id not found in model associator on BookmarkNodeChanged"); | 221 "Bookmark id not found in model associator on BookmarkNodeChanged"); |
| 222 LOG(ERROR) << "Bad id."; | 222 LOG(ERROR) << "Bad id."; |
| 223 } else if (!sync_node.GetEntry()->good()) { | 223 } else if (!sync_node.GetEntry()->good()) { |
| 224 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 224 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 225 "Could not InitByIdLookup on BookmarkNodeChanged, good() failed"); | 225 "Could not InitByIdLookup on BookmarkNodeChanged, good() failed"); |
| 226 LOG(ERROR) << "Bad entry."; | 226 LOG(ERROR) << "Bad entry."; |
| 227 } else if (sync_node.GetEntry()->Get(syncable::IS_DEL)) { | 227 } else if (sync_node.GetEntry()->Get(syncable::IS_DEL)) { |
| 228 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 228 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 229 "Could not InitByIdLookup on BookmarkNodeChanged, is_del true"); | 229 "Could not InitByIdLookup on BookmarkNodeChanged, is_del true"); |
| 230 LOG(ERROR) << "Deleted entry."; | 230 LOG(ERROR) << "Deleted entry."; |
| 231 } else { | 231 } else { |
| 232 csync::Cryptographer* crypto = trans.GetCryptographer(); | 232 syncer::Cryptographer* crypto = trans.GetCryptographer(); |
| 233 syncable::ModelTypeSet encrypted_types(crypto->GetEncryptedTypes()); | 233 syncable::ModelTypeSet encrypted_types(crypto->GetEncryptedTypes()); |
| 234 const sync_pb::EntitySpecifics& specifics = | 234 const sync_pb::EntitySpecifics& specifics = |
| 235 sync_node.GetEntry()->Get(syncable::SPECIFICS); | 235 sync_node.GetEntry()->Get(syncable::SPECIFICS); |
| 236 CHECK(specifics.has_encrypted()); | 236 CHECK(specifics.has_encrypted()); |
| 237 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); | 237 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); |
| 238 const bool agreement = encrypted_types.Has(syncable::BOOKMARKS); | 238 const bool agreement = encrypted_types.Has(syncable::BOOKMARKS); |
| 239 if (!agreement && !can_decrypt) { | 239 if (!agreement && !can_decrypt) { |
| 240 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 240 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 241 "Could not InitByIdLookup on BookmarkNodeChanged, " | 241 "Could not InitByIdLookup on BookmarkNodeChanged, " |
| 242 " Cryptographer thinks bookmarks not encrypted, and CanDecrypt" | 242 " Cryptographer thinks bookmarks not encrypted, and CanDecrypt" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 const BookmarkNode* new_parent, int new_index) { | 283 const BookmarkNode* new_parent, int new_index) { |
| 284 DCHECK(running()); | 284 DCHECK(running()); |
| 285 const BookmarkNode* child = new_parent->GetChild(new_index); | 285 const BookmarkNode* child = new_parent->GetChild(new_index); |
| 286 // We shouldn't see changes to the top-level nodes. | 286 // We shouldn't see changes to the top-level nodes. |
| 287 if (model->is_permanent_node(child)) { | 287 if (model->is_permanent_node(child)) { |
| 288 NOTREACHED() << "Saw update to permanent node!"; | 288 NOTREACHED() << "Saw update to permanent node!"; |
| 289 return; | 289 return; |
| 290 } | 290 } |
| 291 | 291 |
| 292 // Acquire a scoped write lock via a transaction. | 292 // Acquire a scoped write lock via a transaction. |
| 293 csync::WriteTransaction trans(FROM_HERE, share_handle()); | 293 syncer::WriteTransaction trans(FROM_HERE, share_handle()); |
| 294 | 294 |
| 295 // Lookup the sync node that's associated with |child|. | 295 // Lookup the sync node that's associated with |child|. |
| 296 csync::WriteNode sync_node(&trans); | 296 syncer::WriteNode sync_node(&trans); |
| 297 if (!model_associator_->InitSyncNodeFromChromeId(child->id(), &sync_node)) { | 297 if (!model_associator_->InitSyncNodeFromChromeId(child->id(), &sync_node)) { |
| 298 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 298 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 299 std::string()); | 299 std::string()); |
| 300 return; | 300 return; |
| 301 } | 301 } |
| 302 | 302 |
| 303 if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node, | 303 if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node, |
| 304 model_associator_)) { | 304 model_associator_)) { |
| 305 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 305 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 306 std::string()); | 306 std::string()); |
| 307 return; | 307 return; |
| 308 } | 308 } |
| 309 } | 309 } |
| 310 | 310 |
| 311 void BookmarkChangeProcessor::BookmarkNodeFaviconChanged( | 311 void BookmarkChangeProcessor::BookmarkNodeFaviconChanged( |
| 312 BookmarkModel* model, | 312 BookmarkModel* model, |
| 313 const BookmarkNode* node) { | 313 const BookmarkNode* node) { |
| 314 DCHECK(running()); | 314 DCHECK(running()); |
| 315 BookmarkNodeChanged(model, node); | 315 BookmarkNodeChanged(model, node); |
| 316 } | 316 } |
| 317 | 317 |
| 318 void BookmarkChangeProcessor::BookmarkNodeChildrenReordered( | 318 void BookmarkChangeProcessor::BookmarkNodeChildrenReordered( |
| 319 BookmarkModel* model, const BookmarkNode* node) { | 319 BookmarkModel* model, const BookmarkNode* node) { |
| 320 | 320 |
| 321 // Acquire a scoped write lock via a transaction. | 321 // Acquire a scoped write lock via a transaction. |
| 322 csync::WriteTransaction trans(FROM_HERE, share_handle()); | 322 syncer::WriteTransaction trans(FROM_HERE, share_handle()); |
| 323 | 323 |
| 324 // The given node's children got reordered. We need to reorder all the | 324 // The given node's children got reordered. We need to reorder all the |
| 325 // children of the corresponding sync node. | 325 // children of the corresponding sync node. |
| 326 for (int i = 0; i < node->child_count(); ++i) { | 326 for (int i = 0; i < node->child_count(); ++i) { |
| 327 csync::WriteNode sync_child(&trans); | 327 syncer::WriteNode sync_child(&trans); |
| 328 if (!model_associator_->InitSyncNodeFromChromeId(node->GetChild(i)->id(), | 328 if (!model_associator_->InitSyncNodeFromChromeId(node->GetChild(i)->id(), |
| 329 &sync_child)) { | 329 &sync_child)) { |
| 330 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 330 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 331 std::string()); | 331 std::string()); |
| 332 return; | 332 return; |
| 333 } | 333 } |
| 334 DCHECK_EQ(sync_child.GetParentId(), | 334 DCHECK_EQ(sync_child.GetParentId(), |
| 335 model_associator_->GetSyncIdFromChromeId(node->id())); | 335 model_associator_->GetSyncIdFromChromeId(node->id())); |
| 336 | 336 |
| 337 if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child, | 337 if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child, |
| 338 model_associator_)) { | 338 model_associator_)) { |
| 339 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 339 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 340 std::string()); | 340 std::string()); |
| 341 return; | 341 return; |
| 342 } | 342 } |
| 343 } | 343 } |
| 344 } | 344 } |
| 345 | 345 |
| 346 // static | 346 // static |
| 347 bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation, | 347 bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation, |
| 348 const BookmarkNode* parent, int index, csync::WriteTransaction* trans, | 348 const BookmarkNode* parent, int index, syncer::WriteTransaction* trans, |
| 349 csync::WriteNode* dst, BookmarkModelAssociator* associator) { | 349 syncer::WriteNode* dst, BookmarkModelAssociator* associator) { |
| 350 csync::ReadNode sync_parent(trans); | 350 syncer::ReadNode sync_parent(trans); |
| 351 if (!associator->InitSyncNodeFromChromeId(parent->id(), &sync_parent)) { | 351 if (!associator->InitSyncNodeFromChromeId(parent->id(), &sync_parent)) { |
| 352 LOG(WARNING) << "Parent lookup failed"; | 352 LOG(WARNING) << "Parent lookup failed"; |
| 353 return false; | 353 return false; |
| 354 } | 354 } |
| 355 | 355 |
| 356 bool success = false; | 356 bool success = false; |
| 357 if (index == 0) { | 357 if (index == 0) { |
| 358 // Insert into first position. | 358 // Insert into first position. |
| 359 success = (operation == CREATE) ? | 359 success = (operation == CREATE) ? |
| 360 dst->InitByCreation(syncable::BOOKMARKS, sync_parent, NULL) : | 360 dst->InitByCreation(syncable::BOOKMARKS, sync_parent, NULL) : |
| 361 dst->SetPosition(sync_parent, NULL); | 361 dst->SetPosition(sync_parent, NULL); |
| 362 if (success) { | 362 if (success) { |
| 363 DCHECK_EQ(dst->GetParentId(), sync_parent.GetId()); | 363 DCHECK_EQ(dst->GetParentId(), sync_parent.GetId()); |
| 364 DCHECK_EQ(dst->GetId(), sync_parent.GetFirstChildId()); | 364 DCHECK_EQ(dst->GetId(), sync_parent.GetFirstChildId()); |
| 365 DCHECK_EQ(dst->GetPredecessorId(), csync::kInvalidId); | 365 DCHECK_EQ(dst->GetPredecessorId(), syncer::kInvalidId); |
| 366 } | 366 } |
| 367 } else { | 367 } else { |
| 368 // Find the bookmark model predecessor, and insert after it. | 368 // Find the bookmark model predecessor, and insert after it. |
| 369 const BookmarkNode* prev = parent->GetChild(index - 1); | 369 const BookmarkNode* prev = parent->GetChild(index - 1); |
| 370 csync::ReadNode sync_prev(trans); | 370 syncer::ReadNode sync_prev(trans); |
| 371 if (!associator->InitSyncNodeFromChromeId(prev->id(), &sync_prev)) { | 371 if (!associator->InitSyncNodeFromChromeId(prev->id(), &sync_prev)) { |
| 372 LOG(WARNING) << "Predecessor lookup failed"; | 372 LOG(WARNING) << "Predecessor lookup failed"; |
| 373 return false; | 373 return false; |
| 374 } | 374 } |
| 375 success = (operation == CREATE) ? | 375 success = (operation == CREATE) ? |
| 376 dst->InitByCreation(syncable::BOOKMARKS, sync_parent, &sync_prev) : | 376 dst->InitByCreation(syncable::BOOKMARKS, sync_parent, &sync_prev) : |
| 377 dst->SetPosition(sync_parent, &sync_prev); | 377 dst->SetPosition(sync_parent, &sync_prev); |
| 378 if (success) { | 378 if (success) { |
| 379 DCHECK_EQ(dst->GetParentId(), sync_parent.GetId()); | 379 DCHECK_EQ(dst->GetParentId(), sync_parent.GetId()); |
| 380 DCHECK_EQ(dst->GetPredecessorId(), sync_prev.GetId()); | 380 DCHECK_EQ(dst->GetPredecessorId(), sync_prev.GetId()); |
| 381 DCHECK_EQ(dst->GetId(), sync_prev.GetSuccessorId()); | 381 DCHECK_EQ(dst->GetId(), sync_prev.GetSuccessorId()); |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 return success; | 384 return success; |
| 385 } | 385 } |
| 386 | 386 |
| 387 // Determine the bookmark model index to which a node must be moved so that | 387 // Determine the bookmark model index to which a node must be moved so that |
| 388 // predecessor of the node (in the bookmark model) matches the predecessor of | 388 // predecessor of the node (in the bookmark model) matches the predecessor of |
| 389 // |source| (in the sync model). | 389 // |source| (in the sync model). |
| 390 // As a precondition, this assumes that the predecessor of |source| has been | 390 // As a precondition, this assumes that the predecessor of |source| has been |
| 391 // updated and is already in the correct position in the bookmark model. | 391 // updated and is already in the correct position in the bookmark model. |
| 392 int BookmarkChangeProcessor::CalculateBookmarkModelInsertionIndex( | 392 int BookmarkChangeProcessor::CalculateBookmarkModelInsertionIndex( |
| 393 const BookmarkNode* parent, | 393 const BookmarkNode* parent, |
| 394 const csync::BaseNode* child_info) const { | 394 const syncer::BaseNode* child_info) const { |
| 395 DCHECK(parent); | 395 DCHECK(parent); |
| 396 DCHECK(child_info); | 396 DCHECK(child_info); |
| 397 int64 predecessor_id = child_info->GetPredecessorId(); | 397 int64 predecessor_id = child_info->GetPredecessorId(); |
| 398 // A return ID of kInvalidId indicates no predecessor. | 398 // A return ID of kInvalidId indicates no predecessor. |
| 399 if (predecessor_id == csync::kInvalidId) | 399 if (predecessor_id == syncer::kInvalidId) |
| 400 return 0; | 400 return 0; |
| 401 | 401 |
| 402 // Otherwise, insert after the predecessor bookmark node. | 402 // Otherwise, insert after the predecessor bookmark node. |
| 403 const BookmarkNode* predecessor = | 403 const BookmarkNode* predecessor = |
| 404 model_associator_->GetChromeNodeFromSyncId(predecessor_id); | 404 model_associator_->GetChromeNodeFromSyncId(predecessor_id); |
| 405 DCHECK(predecessor); | 405 DCHECK(predecessor); |
| 406 DCHECK_EQ(predecessor->parent(), parent); | 406 DCHECK_EQ(predecessor->parent(), parent); |
| 407 return parent->GetIndexOf(predecessor) + 1; | 407 return parent->GetIndexOf(predecessor) + 1; |
| 408 } | 408 } |
| 409 | 409 |
| 410 // ApplyModelChanges is called by the sync backend after changes have been made | 410 // ApplyModelChanges is called by the sync backend after changes have been made |
| 411 // to the sync engine's model. Apply these changes to the browser bookmark | 411 // to the sync engine's model. Apply these changes to the browser bookmark |
| 412 // model. | 412 // model. |
| 413 void BookmarkChangeProcessor::ApplyChangesFromSyncModel( | 413 void BookmarkChangeProcessor::ApplyChangesFromSyncModel( |
| 414 const csync::BaseTransaction* trans, | 414 const syncer::BaseTransaction* trans, |
| 415 const csync::ImmutableChangeRecordList& changes) { | 415 const syncer::ImmutableChangeRecordList& changes) { |
| 416 if (!running()) | 416 if (!running()) |
| 417 return; | 417 return; |
| 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 419 // A note about ordering. Sync backend is responsible for ordering the change | 419 // A note about ordering. Sync backend is responsible for ordering the change |
| 420 // records in the following order: | 420 // records in the following order: |
| 421 // | 421 // |
| 422 // 1. Deletions, from leaves up to parents. | 422 // 1. Deletions, from leaves up to parents. |
| 423 // 2. Existing items with synced parents & predecessors. | 423 // 2. Existing items with synced parents & predecessors. |
| 424 // 3. New items with synced parents & predecessors. | 424 // 3. New items with synced parents & predecessors. |
| 425 // 4. Items with parents & predecessors in the list. | 425 // 4. Items with parents & predecessors in the list. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 439 // changes. | 439 // changes. |
| 440 model->RemoveObserver(this); | 440 model->RemoveObserver(this); |
| 441 | 441 |
| 442 // A parent to hold nodes temporarily orphaned by parent deletion. It is | 442 // A parent to hold nodes temporarily orphaned by parent deletion. It is |
| 443 // lazily created inside the loop. | 443 // lazily created inside the loop. |
| 444 const BookmarkNode* foster_parent = NULL; | 444 const BookmarkNode* foster_parent = NULL; |
| 445 | 445 |
| 446 // Whether we have passed all the deletes (which should be at the | 446 // Whether we have passed all the deletes (which should be at the |
| 447 // front of the list). | 447 // front of the list). |
| 448 bool passed_deletes = false; | 448 bool passed_deletes = false; |
| 449 for (csync::ChangeRecordList::const_iterator it = | 449 for (syncer::ChangeRecordList::const_iterator it = |
| 450 changes.Get().begin(); it != changes.Get().end(); ++it) { | 450 changes.Get().begin(); it != changes.Get().end(); ++it) { |
| 451 const BookmarkNode* dst = | 451 const BookmarkNode* dst = |
| 452 model_associator_->GetChromeNodeFromSyncId(it->id); | 452 model_associator_->GetChromeNodeFromSyncId(it->id); |
| 453 // Ignore changes to the permanent top-level nodes. We only care about | 453 // Ignore changes to the permanent top-level nodes. We only care about |
| 454 // their children. | 454 // their children. |
| 455 if (model->is_permanent_node(dst)) | 455 if (model->is_permanent_node(dst)) |
| 456 continue; | 456 continue; |
| 457 if (it->action == | 457 if (it->action == |
| 458 csync::ChangeRecord::ACTION_DELETE) { | 458 syncer::ChangeRecord::ACTION_DELETE) { |
| 459 // Deletions should always be at the front of the list. | 459 // Deletions should always be at the front of the list. |
| 460 DCHECK(!passed_deletes); | 460 DCHECK(!passed_deletes); |
| 461 // Children of a deleted node should not be deleted; they may be | 461 // Children of a deleted node should not be deleted; they may be |
| 462 // reparented by a later change record. Move them to a temporary place. | 462 // reparented by a later change record. Move them to a temporary place. |
| 463 if (!dst) // Can't do anything if we can't find the chrome node. | 463 if (!dst) // Can't do anything if we can't find the chrome node. |
| 464 continue; | 464 continue; |
| 465 const BookmarkNode* parent = dst->parent(); | 465 const BookmarkNode* parent = dst->parent(); |
| 466 if (!dst->empty()) { | 466 if (!dst->empty()) { |
| 467 if (!foster_parent) { | 467 if (!foster_parent) { |
| 468 foster_parent = model->AddFolder(model->other_node(), | 468 foster_parent = model->AddFolder(model->other_node(), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 480 } | 480 } |
| 481 } | 481 } |
| 482 DCHECK_EQ(dst->child_count(), 0) << "Node being deleted has children"; | 482 DCHECK_EQ(dst->child_count(), 0) << "Node being deleted has children"; |
| 483 model_associator_->Disassociate(it->id); | 483 model_associator_->Disassociate(it->id); |
| 484 int index = parent->GetIndexOf(dst); | 484 int index = parent->GetIndexOf(dst); |
| 485 if (index > -1) | 485 if (index > -1) |
| 486 model->Remove(parent, index); | 486 model->Remove(parent, index); |
| 487 dst = NULL; | 487 dst = NULL; |
| 488 } else { | 488 } else { |
| 489 DCHECK_EQ((it->action == | 489 DCHECK_EQ((it->action == |
| 490 csync::ChangeRecord::ACTION_ADD), (dst == NULL)) | 490 syncer::ChangeRecord::ACTION_ADD), (dst == NULL)) |
| 491 << "ACTION_ADD should be seen if and only if the node is unknown."; | 491 << "ACTION_ADD should be seen if and only if the node is unknown."; |
| 492 passed_deletes = true; | 492 passed_deletes = true; |
| 493 | 493 |
| 494 csync::ReadNode src(trans); | 494 syncer::ReadNode src(trans); |
| 495 if (src.InitByIdLookup(it->id) != csync::BaseNode::INIT_OK) { | 495 if (src.InitByIdLookup(it->id) != syncer::BaseNode::INIT_OK) { |
| 496 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 496 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 497 "ApplyModelChanges was passed a bad ID"); | 497 "ApplyModelChanges was passed a bad ID"); |
| 498 return; | 498 return; |
| 499 } | 499 } |
| 500 | 500 |
| 501 if (!CreateOrUpdateBookmarkNode(&src, model)) { | 501 if (!CreateOrUpdateBookmarkNode(&src, model)) { |
| 502 // Because the Synced Bookmarks node can be created server side, it's | 502 // Because the Synced Bookmarks node can be created server side, it's |
| 503 // possible it'll arrive at the client as an update. In that case it | 503 // possible it'll arrive at the client as an update. In that case it |
| 504 // won't have been associated at startup, the GetChromeNodeFromSyncId | 504 // won't have been associated at startup, the GetChromeNodeFromSyncId |
| 505 // call above will return NULL, and we won't detect it as a permanent | 505 // call above will return NULL, and we won't detect it as a permanent |
| 506 // node, resulting in us trying to create it here (which will | 506 // node, resulting in us trying to create it here (which will |
| 507 // fail). Therefore, we add special logic here just to detect the | 507 // fail). Therefore, we add special logic here just to detect the |
| 508 // Synced Bookmarks folder. | 508 // Synced Bookmarks folder. |
| 509 csync::ReadNode synced_bookmarks(trans); | 509 syncer::ReadNode synced_bookmarks(trans); |
| 510 if (synced_bookmarks.InitByTagLookup(kMobileBookmarksTag) == | 510 if (synced_bookmarks.InitByTagLookup(kMobileBookmarksTag) == |
| 511 csync::BaseNode::INIT_OK && | 511 syncer::BaseNode::INIT_OK && |
| 512 synced_bookmarks.GetId() == it->id) { | 512 synced_bookmarks.GetId() == it->id) { |
| 513 // This is a newly created Synced Bookmarks node. Associate it. | 513 // This is a newly created Synced Bookmarks node. Associate it. |
| 514 model_associator_->Associate(model->mobile_node(), it->id); | 514 model_associator_->Associate(model->mobile_node(), it->id); |
| 515 } else { | 515 } else { |
| 516 // We ignore bookmarks we can't add. Chances are this is caused by | 516 // We ignore bookmarks we can't add. Chances are this is caused by |
| 517 // a bookmark that was not fully associated. | 517 // a bookmark that was not fully associated. |
| 518 LOG(ERROR) << "Failed to create bookmark node with title " | 518 LOG(ERROR) << "Failed to create bookmark node with title " |
| 519 << src.GetTitle() + " and url " | 519 << src.GetTitle() + " and url " |
| 520 << src.GetURL().possibly_invalid_spec(); | 520 << src.GetURL().possibly_invalid_spec(); |
| 521 } | 521 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 534 // The visibility of the mobile node may need to change. | 534 // The visibility of the mobile node may need to change. |
| 535 model_associator_->UpdatePermanentNodeVisibility(); | 535 model_associator_->UpdatePermanentNodeVisibility(); |
| 536 | 536 |
| 537 // We are now ready to hear about bookmarks changes again. | 537 // We are now ready to hear about bookmarks changes again. |
| 538 model->AddObserver(this); | 538 model->AddObserver(this); |
| 539 } | 539 } |
| 540 | 540 |
| 541 // Create a bookmark node corresponding to |src| if one is not already | 541 // Create a bookmark node corresponding to |src| if one is not already |
| 542 // associated with |src|. | 542 // associated with |src|. |
| 543 const BookmarkNode* BookmarkChangeProcessor::CreateOrUpdateBookmarkNode( | 543 const BookmarkNode* BookmarkChangeProcessor::CreateOrUpdateBookmarkNode( |
| 544 csync::BaseNode* src, | 544 syncer::BaseNode* src, |
| 545 BookmarkModel* model) { | 545 BookmarkModel* model) { |
| 546 const BookmarkNode* parent = | 546 const BookmarkNode* parent = |
| 547 model_associator_->GetChromeNodeFromSyncId(src->GetParentId()); | 547 model_associator_->GetChromeNodeFromSyncId(src->GetParentId()); |
| 548 if (!parent) { | 548 if (!parent) { |
| 549 DLOG(WARNING) << "Could not find parent of node being added/updated." | 549 DLOG(WARNING) << "Could not find parent of node being added/updated." |
| 550 << " Node title: " << src->GetTitle() | 550 << " Node title: " << src->GetTitle() |
| 551 << ", parent id = " << src->GetParentId(); | 551 << ", parent id = " << src->GetParentId(); |
| 552 | 552 |
| 553 return NULL; | 553 return NULL; |
| 554 } | 554 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 574 SetBookmarkFavicon(src, dst, model); | 574 SetBookmarkFavicon(src, dst, model); |
| 575 } | 575 } |
| 576 | 576 |
| 577 return dst; | 577 return dst; |
| 578 } | 578 } |
| 579 | 579 |
| 580 // static | 580 // static |
| 581 // Creates a bookmark node under the given parent node from the given sync | 581 // Creates a bookmark node under the given parent node from the given sync |
| 582 // node. Returns the newly created node. | 582 // node. Returns the newly created node. |
| 583 const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode( | 583 const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode( |
| 584 csync::BaseNode* sync_node, | 584 syncer::BaseNode* sync_node, |
| 585 const BookmarkNode* parent, | 585 const BookmarkNode* parent, |
| 586 BookmarkModel* model, | 586 BookmarkModel* model, |
| 587 int index) { | 587 int index) { |
| 588 DCHECK(parent); | 588 DCHECK(parent); |
| 589 DCHECK(index >= 0 && index <= parent->child_count()); | 589 DCHECK(index >= 0 && index <= parent->child_count()); |
| 590 | 590 |
| 591 const BookmarkNode* node; | 591 const BookmarkNode* node; |
| 592 if (sync_node->GetIsFolder()) { | 592 if (sync_node->GetIsFolder()) { |
| 593 node = model->AddFolder(parent, index, | 593 node = model->AddFolder(parent, index, |
| 594 UTF8ToUTF16(sync_node->GetTitle())); | 594 UTF8ToUTF16(sync_node->GetTitle())); |
| 595 } else { | 595 } else { |
| 596 node = model->AddURL(parent, index, | 596 node = model->AddURL(parent, index, |
| 597 UTF8ToUTF16(sync_node->GetTitle()), | 597 UTF8ToUTF16(sync_node->GetTitle()), |
| 598 sync_node->GetURL()); | 598 sync_node->GetURL()); |
| 599 if (node) | 599 if (node) |
| 600 SetBookmarkFavicon(sync_node, node, model); | 600 SetBookmarkFavicon(sync_node, node, model); |
| 601 } | 601 } |
| 602 return node; | 602 return node; |
| 603 } | 603 } |
| 604 | 604 |
| 605 // static | 605 // static |
| 606 // Sets the favicon of the given bookmark node from the given sync node. | 606 // Sets the favicon of the given bookmark node from the given sync node. |
| 607 bool BookmarkChangeProcessor::SetBookmarkFavicon( | 607 bool BookmarkChangeProcessor::SetBookmarkFavicon( |
| 608 csync::BaseNode* sync_node, | 608 syncer::BaseNode* sync_node, |
| 609 const BookmarkNode* bookmark_node, | 609 const BookmarkNode* bookmark_node, |
| 610 BookmarkModel* bookmark_model) { | 610 BookmarkModel* bookmark_model) { |
| 611 std::vector<unsigned char> icon_bytes_vector; | 611 std::vector<unsigned char> icon_bytes_vector; |
| 612 sync_node->GetFaviconBytes(&icon_bytes_vector); | 612 sync_node->GetFaviconBytes(&icon_bytes_vector); |
| 613 if (icon_bytes_vector.empty()) | 613 if (icon_bytes_vector.empty()) |
| 614 return false; | 614 return false; |
| 615 | 615 |
| 616 ApplyBookmarkFavicon(bookmark_node, bookmark_model->profile(), | 616 ApplyBookmarkFavicon(bookmark_node, bookmark_model->profile(), |
| 617 icon_bytes_vector); | 617 icon_bytes_vector); |
| 618 | 618 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 642 favicon_service->SetFavicon(bookmark_node->url(), | 642 favicon_service->SetFavicon(bookmark_node->url(), |
| 643 fake_icon_url, | 643 fake_icon_url, |
| 644 icon_bytes_vector, | 644 icon_bytes_vector, |
| 645 history::FAVICON); | 645 history::FAVICON); |
| 646 } | 646 } |
| 647 | 647 |
| 648 // static | 648 // static |
| 649 void BookmarkChangeProcessor::SetSyncNodeFavicon( | 649 void BookmarkChangeProcessor::SetSyncNodeFavicon( |
| 650 const BookmarkNode* bookmark_node, | 650 const BookmarkNode* bookmark_node, |
| 651 BookmarkModel* model, | 651 BookmarkModel* model, |
| 652 csync::WriteNode* sync_node) { | 652 syncer::WriteNode* sync_node) { |
| 653 std::vector<unsigned char> favicon_bytes; | 653 std::vector<unsigned char> favicon_bytes; |
| 654 EncodeFavicon(bookmark_node, model, &favicon_bytes); | 654 EncodeFavicon(bookmark_node, model, &favicon_bytes); |
| 655 if (!favicon_bytes.empty()) | 655 if (!favicon_bytes.empty()) |
| 656 sync_node->SetFaviconBytes(favicon_bytes); | 656 sync_node->SetFaviconBytes(favicon_bytes); |
| 657 } | 657 } |
| 658 | 658 |
| 659 } // namespace browser_sync | 659 } // namespace browser_sync |
| OLD | NEW |