OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/sync_driver/generic_change_processor.h" | 5 #include "components/sync_driver/generic_change_processor.h" |
6 | 6 |
7 #include "base/location.h" | 7 #include "base/location.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "sync/api/sync_change.h" | 10 #include "sync/api/sync_change.h" |
(...skipping 18 matching lines...) Expand all Loading... | |
29 syncer::WriteNode* write_node) { | 29 syncer::WriteNode* write_node) { |
30 if (syncer::GetModelTypeFromSpecifics(entity_specifics) == | 30 if (syncer::GetModelTypeFromSpecifics(entity_specifics) == |
31 syncer::PASSWORDS) { | 31 syncer::PASSWORDS) { |
32 write_node->SetPasswordSpecifics( | 32 write_node->SetPasswordSpecifics( |
33 entity_specifics.password().client_only_encrypted_data()); | 33 entity_specifics.password().client_only_encrypted_data()); |
34 } else { | 34 } else { |
35 write_node->SetEntitySpecifics(entity_specifics); | 35 write_node->SetEntitySpecifics(entity_specifics); |
36 } | 36 } |
37 } | 37 } |
38 | 38 |
39 // Helper function to convert AttachmentId to AttachmentMetadataRecord. | |
40 sync_pb::AttachmentMetadataRecord AttachmentIdToRecord( | |
41 const syncer::AttachmentId& attachment_id) { | |
42 sync_pb::AttachmentMetadataRecord record; | |
43 *record.mutable_id() = attachment_id.GetProto(); | |
44 return record; | |
45 } | |
46 | |
47 // Replace |write_nodes|'s attachment ids with |attachment_ids|. | |
48 void SetAttachmentMetadata(const syncer::AttachmentIdList& attachment_ids, | |
49 syncer::WriteNode* write_node) { | |
50 DCHECK(write_node); | |
51 sync_pb::AttachmentMetadata attachment_metadata; | |
52 std::transform( | |
53 attachment_ids.begin(), | |
54 attachment_ids.end(), | |
55 RepeatedFieldBackInserter(attachment_metadata.mutable_record()), | |
56 AttachmentIdToRecord); | |
57 write_node->SetAttachmentMetadata(attachment_metadata); | |
58 } | |
59 | |
39 syncer::SyncData BuildRemoteSyncData( | 60 syncer::SyncData BuildRemoteSyncData( |
40 int64 sync_id, | 61 int64 sync_id, |
41 const syncer::BaseNode& read_node, | 62 const syncer::BaseNode& read_node, |
42 const syncer::AttachmentServiceProxy& attachment_service_proxy) { | 63 const syncer::AttachmentServiceProxy& attachment_service_proxy) { |
43 const syncer::AttachmentIdList& attachment_ids = read_node.GetAttachmentIds(); | 64 const syncer::AttachmentIdList& attachment_ids = read_node.GetAttachmentIds(); |
44 // Use the specifics of non-password datatypes directly (encryption has | 65 // Use the specifics of non-password datatypes directly (encryption has |
45 // already been handled). | 66 // already been handled). |
46 if (read_node.GetModelType() != syncer::PASSWORDS) { | 67 if (read_node.GetModelType() != syncer::PASSWORDS) { |
47 return syncer::SyncData::CreateRemoteData(sync_id, | 68 return syncer::SyncData::CreateRemoteData(sync_id, |
48 read_node.GetEntitySpecifics(), | 69 read_node.GetEntitySpecifics(), |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 // Should have listed all the possible error cases above. | 333 // Should have listed all the possible error cases above. |
313 error.Reset(from_here, error_prefix + "unknown error", type); | 334 error.Reset(from_here, error_prefix + "unknown error", type); |
314 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 335 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
315 error.message()); | 336 error.message()); |
316 LOG(ERROR) << "Delete: Unknown error."; | 337 LOG(ERROR) << "Delete: Unknown error."; |
317 return error; | 338 return error; |
318 } | 339 } |
319 } | 340 } |
320 } | 341 } |
321 | 342 |
322 syncer::SyncError AttemptDelete( | 343 syncer::SyncError AttemptDelete(const syncer::SyncChange& change, |
323 const syncer::SyncChange& change, | |
324 syncer::ModelType type, | 344 syncer::ModelType type, |
pavely
2014/04/28 23:26:27
nit: Indentation is off.
maniscalco
2014/04/29 20:53:22
Fixed (and ran through "git cl format").
| |
325 const std::string& type_str, | 345 const std::string& type_str, |
326 syncer::WriteNode* node, | 346 syncer::WriteNode* node, |
327 DataTypeErrorHandler* error_handler) { | 347 DataTypeErrorHandler* error_handler) { |
328 DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE); | 348 DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE); |
329 if (change.sync_data().IsLocal()) { | 349 if (change.sync_data().IsLocal()) { |
330 const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); | 350 const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); |
331 if (tag.empty()) { | 351 if (tag.empty()) { |
332 syncer::SyncError error( | 352 syncer::SyncError error( |
333 FROM_HERE, | 353 FROM_HERE, |
334 syncer::SyncError::DATATYPE_ERROR, | 354 syncer::SyncError::DATATYPE_ERROR, |
(...skipping 26 matching lines...) Expand all Loading... | |
361 type, error_handler); | 381 type, error_handler); |
362 } | 382 } |
363 } | 383 } |
364 if (IsActOnceDataType(type)) | 384 if (IsActOnceDataType(type)) |
365 node->Drop(); | 385 node->Drop(); |
366 else | 386 else |
367 node->Tombstone(); | 387 node->Tombstone(); |
368 return syncer::SyncError(); | 388 return syncer::SyncError(); |
369 } | 389 } |
370 | 390 |
391 // A callback invoked on completion of AttachmentService::StoreAttachment. | |
392 void IgnoreStoreResult(const syncer::AttachmentService::StoreResult&) { | |
393 // TODO(maniscalco): Log errors? | |
394 } | |
395 | |
396 void StoreAttachments(syncer::AttachmentService* attachment_service, | |
397 const syncer::AttachmentList& attachments) { | |
398 DCHECK(attachment_service); | |
399 syncer::AttachmentService::StoreCallback ignore_store_result = | |
400 base::Bind(&IgnoreStoreResult); | |
401 attachment_service->StoreAttachments(attachments, ignore_store_result); | |
402 } | |
403 | |
371 } // namespace | 404 } // namespace |
372 | 405 |
373 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( | 406 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( |
374 const tracked_objects::Location& from_here, | 407 const tracked_objects::Location& from_here, |
375 const syncer::SyncChangeList& list_of_changes) { | 408 const syncer::SyncChangeList& list_of_changes) { |
376 DCHECK(CalledOnValidThread()); | 409 DCHECK(CalledOnValidThread()); |
410 | |
411 // Keep track of brand new attachments so we can persist them on this device | |
412 // and upload them to the server. | |
413 syncer::AttachmentList new_attachments; | |
414 | |
377 syncer::WriteTransaction trans(from_here, share_handle()); | 415 syncer::WriteTransaction trans(from_here, share_handle()); |
378 | 416 |
379 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); | 417 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); |
380 iter != list_of_changes.end(); | 418 iter != list_of_changes.end(); |
381 ++iter) { | 419 ++iter) { |
382 const syncer::SyncChange& change = *iter; | 420 const syncer::SyncChange& change = *iter; |
383 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED); | 421 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED); |
384 syncer::ModelType type = change.sync_data().GetDataType(); | 422 syncer::ModelType type = change.sync_data().GetDataType(); |
385 std::string type_str = syncer::ModelTypeToString(type); | 423 std::string type_str = syncer::ModelTypeToString(type); |
386 syncer::WriteNode sync_node(&trans); | 424 syncer::WriteNode sync_node(&trans); |
387 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) { | 425 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) { |
388 syncer::SyncError error = | 426 syncer::SyncError error = |
389 AttemptDelete(change, type, type_str, &sync_node, error_handler()); | 427 AttemptDelete(change, type, type_str, &sync_node, error_handler()); |
390 if (error.IsSet()) { | 428 if (error.IsSet()) { |
391 NOTREACHED(); | 429 NOTREACHED(); |
392 return error; | 430 return error; |
393 } | 431 } |
394 attachment_service_->OnSyncDataDelete(change.sync_data()); | |
395 if (merge_result_.get()) { | 432 if (merge_result_.get()) { |
396 merge_result_->set_num_items_deleted( | 433 merge_result_->set_num_items_deleted( |
397 merge_result_->num_items_deleted() + 1); | 434 merge_result_->num_items_deleted() + 1); |
398 } | 435 } |
399 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { | 436 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { |
400 syncer::SyncError error = | 437 syncer::SyncError error = HandleActionAdd( |
401 HandleActionAdd(change, type_str, type, trans, &sync_node); | 438 change, type_str, type, trans, &sync_node, &new_attachments); |
402 if (error.IsSet()) { | 439 if (error.IsSet()) { |
403 return error; | 440 return error; |
404 } | 441 } |
405 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { | 442 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { |
406 syncer::SyncError error = | 443 syncer::SyncError error = HandleActionUpdate( |
407 HandleActionUpdate(change, type_str, type, trans, &sync_node); | 444 change, type_str, type, trans, &sync_node, &new_attachments); |
408 if (error.IsSet()) { | 445 if (error.IsSet()) { |
409 return error; | 446 return error; |
410 } | 447 } |
411 } else { | 448 } else { |
412 syncer::SyncError error( | 449 syncer::SyncError error( |
413 FROM_HERE, | 450 FROM_HERE, |
414 syncer::SyncError::DATATYPE_ERROR, | 451 syncer::SyncError::DATATYPE_ERROR, |
415 "Received unset SyncChange in the change processor, " + | 452 "Received unset SyncChange in the change processor, " + |
416 change.location().ToString(), | 453 change.location().ToString(), |
417 type); | 454 type); |
418 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 455 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
419 error.message()); | 456 error.message()); |
420 NOTREACHED(); | 457 NOTREACHED(); |
421 LOG(ERROR) << "Unset sync change."; | 458 LOG(ERROR) << "Unset sync change."; |
422 return error; | 459 return error; |
423 } | 460 } |
424 } | 461 } |
462 | |
463 if (!new_attachments.empty()) { | |
464 StoreAttachments(attachment_service_.get(), new_attachments); | |
465 } | |
466 | |
425 return syncer::SyncError(); | 467 return syncer::SyncError(); |
426 } | 468 } |
427 | 469 |
428 // WARNING: this code is sensitive to compiler optimizations. Be careful | 470 // WARNING: this code is sensitive to compiler optimizations. Be careful |
429 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else | 471 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else |
430 // the compiler attempts to merge it with other calls, losing useful information | 472 // the compiler attempts to merge it with other calls, losing useful information |
431 // in breakpad uploads. | 473 // in breakpad uploads. |
432 syncer::SyncError GenericChangeProcessor::HandleActionAdd( | 474 syncer::SyncError GenericChangeProcessor::HandleActionAdd( |
433 const syncer::SyncChange& change, | 475 const syncer::SyncChange& change, |
434 const std::string& type_str, | 476 const std::string& type_str, |
435 const syncer::ModelType& type, | 477 const syncer::ModelType& type, |
436 const syncer::WriteTransaction& trans, | 478 const syncer::WriteTransaction& trans, |
437 syncer::WriteNode* sync_node) { | 479 syncer::WriteNode* sync_node, |
480 syncer::AttachmentList* new_attachments) { | |
438 // TODO(sync): Handle other types of creation (custom parents, folders, | 481 // TODO(sync): Handle other types of creation (custom parents, folders, |
439 // etc.). | 482 // etc.). |
440 syncer::ReadNode root_node(&trans); | 483 syncer::ReadNode root_node(&trans); |
484 const syncer::SyncDataLocal sync_data_local(change.sync_data()); | |
441 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag( | 485 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag( |
442 change.sync_data().GetDataType())) != syncer::BaseNode::INIT_OK) { | 486 sync_data_local.GetDataType())) != syncer::BaseNode::INIT_OK) { |
443 syncer::SyncError error(FROM_HERE, | 487 syncer::SyncError error(FROM_HERE, |
444 syncer::SyncError::DATATYPE_ERROR, | 488 syncer::SyncError::DATATYPE_ERROR, |
445 "Failed to look up root node for type " + type_str, | 489 "Failed to look up root node for type " + type_str, |
446 type); | 490 type); |
447 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 491 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
448 error.message()); | 492 error.message()); |
449 NOTREACHED(); | 493 NOTREACHED(); |
450 LOG(ERROR) << "Create: no root node."; | 494 LOG(ERROR) << "Create: no root node."; |
451 return error; | 495 return error; |
452 } | 496 } |
453 syncer::WriteNode::InitUniqueByCreationResult result = | 497 syncer::WriteNode::InitUniqueByCreationResult result = |
454 sync_node->InitUniqueByCreation( | 498 sync_node->InitUniqueByCreation( |
455 change.sync_data().GetDataType(), | 499 sync_data_local.GetDataType(), root_node, sync_data_local.GetTag()); |
456 root_node, | |
457 syncer::SyncDataLocal(change.sync_data()).GetTag()); | |
458 if (result != syncer::WriteNode::INIT_SUCCESS) { | 500 if (result != syncer::WriteNode::INIT_SUCCESS) { |
459 std::string error_prefix = "Failed to create " + type_str + " node: " + | 501 std::string error_prefix = "Failed to create " + type_str + " node: " + |
460 change.location().ToString() + ", "; | 502 change.location().ToString() + ", "; |
461 switch (result) { | 503 switch (result) { |
462 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: { | 504 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: { |
463 syncer::SyncError error; | 505 syncer::SyncError error; |
464 error.Reset(FROM_HERE, error_prefix + "empty tag", type); | 506 error.Reset(FROM_HERE, error_prefix + "empty tag", type); |
465 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 507 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
466 error.message()); | 508 error.message()); |
467 LOG(ERROR) << "Create: Empty tag."; | 509 LOG(ERROR) << "Create: Empty tag."; |
(...skipping 28 matching lines...) Expand all Loading... | |
496 syncer::SyncError error; | 538 syncer::SyncError error; |
497 error.Reset(FROM_HERE, error_prefix + "unknown error", type); | 539 error.Reset(FROM_HERE, error_prefix + "unknown error", type); |
498 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 540 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
499 error.message()); | 541 error.message()); |
500 LOG(ERROR) << "Create: Unknown error."; | 542 LOG(ERROR) << "Create: Unknown error."; |
501 return error; | 543 return error; |
502 } | 544 } |
503 } | 545 } |
504 } | 546 } |
505 sync_node->SetTitle(change.sync_data().GetTitle()); | 547 sync_node->SetTitle(change.sync_data().GetTitle()); |
506 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); | 548 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
507 attachment_service_->OnSyncDataAdd(change.sync_data()); | 549 |
550 syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); | |
551 SetAttachmentMetadata(attachment_ids, sync_node); | |
552 | |
553 // Return any newly added attachments. | |
554 const syncer::AttachmentList& local_attachments_for_upload = | |
555 sync_data_local.GetLocalAttachmentsForUpload(); | |
556 new_attachments->insert(new_attachments->end(), | |
557 local_attachments_for_upload.begin(), | |
558 local_attachments_for_upload.end()); | |
559 | |
508 if (merge_result_.get()) { | 560 if (merge_result_.get()) { |
509 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); | 561 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); |
510 } | 562 } |
511 return syncer::SyncError(); | 563 return syncer::SyncError(); |
512 } | 564 } |
513 // WARNING: this code is sensitive to compiler optimizations. Be careful | 565 // WARNING: this code is sensitive to compiler optimizations. Be careful |
514 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else | 566 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else |
515 // the compiler attempts to merge it with other calls, losing useful information | 567 // the compiler attempts to merge it with other calls, losing useful information |
516 // in breakpad uploads. | 568 // in breakpad uploads. |
517 syncer::SyncError GenericChangeProcessor::HandleActionUpdate( | 569 syncer::SyncError GenericChangeProcessor::HandleActionUpdate( |
518 const syncer::SyncChange& change, | 570 const syncer::SyncChange& change, |
519 const std::string& type_str, | 571 const std::string& type_str, |
520 const syncer::ModelType& type, | 572 const syncer::ModelType& type, |
521 const syncer::WriteTransaction& trans, | 573 const syncer::WriteTransaction& trans, |
522 syncer::WriteNode* sync_node) { | 574 syncer::WriteNode* sync_node, |
575 syncer::AttachmentList* new_attachments) { | |
523 // TODO(zea): consider having this logic for all possible changes? | 576 // TODO(zea): consider having this logic for all possible changes? |
577 | |
578 const syncer::SyncDataLocal sync_data_local(change.sync_data()); | |
524 syncer::BaseNode::InitByLookupResult result = | 579 syncer::BaseNode::InitByLookupResult result = |
525 sync_node->InitByClientTagLookup( | 580 sync_node->InitByClientTagLookup(sync_data_local.GetDataType(), |
526 change.sync_data().GetDataType(), | 581 sync_data_local.GetTag()); |
527 syncer::SyncDataLocal(change.sync_data()).GetTag()); | |
528 if (result != syncer::BaseNode::INIT_OK) { | 582 if (result != syncer::BaseNode::INIT_OK) { |
529 std::string error_prefix = "Failed to load " + type_str + " node. " + | 583 std::string error_prefix = "Failed to load " + type_str + " node. " + |
530 change.location().ToString() + ", "; | 584 change.location().ToString() + ", "; |
531 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) { | 585 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) { |
532 syncer::SyncError error; | 586 syncer::SyncError error; |
533 error.Reset(FROM_HERE, error_prefix + "empty tag", type); | 587 error.Reset(FROM_HERE, error_prefix + "empty tag", type); |
534 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 588 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
535 error.message()); | 589 error.message()); |
536 LOG(ERROR) << "Update: Empty tag."; | 590 LOG(ERROR) << "Update: Empty tag."; |
537 return error; | 591 return error; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 type); | 653 type); |
600 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 654 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
601 error.message()); | 655 error.message()); |
602 LOG(ERROR) << "Update: encr case 4."; | 656 LOG(ERROR) << "Update: encr case 4."; |
603 return error; | 657 return error; |
604 } | 658 } |
605 } | 659 } |
606 } | 660 } |
607 | 661 |
608 sync_node->SetTitle(change.sync_data().GetTitle()); | 662 sync_node->SetTitle(change.sync_data().GetTitle()); |
609 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); | 663 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
610 attachment_service_->OnSyncDataUpdate(sync_node->GetAttachmentIds(), | 664 SetAttachmentMetadata(sync_data_local.GetAttachmentIds(), sync_node); |
611 change.sync_data()); | 665 |
666 // Return any newly added attachments. | |
667 const syncer::AttachmentList& local_attachments_for_upload = | |
668 sync_data_local.GetLocalAttachmentsForUpload(); | |
669 new_attachments->insert(new_attachments->end(), | |
670 local_attachments_for_upload.begin(), | |
671 local_attachments_for_upload.end()); | |
672 | |
612 if (merge_result_.get()) { | 673 if (merge_result_.get()) { |
613 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + | 674 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + |
614 1); | 675 1); |
615 } | 676 } |
616 // TODO(sync): Support updating other parts of the sync node (title, | 677 // TODO(sync): Support updating other parts of the sync node (title, |
617 // successor, parent, etc.). | 678 // successor, parent, etc.). |
618 return syncer::SyncError(); | 679 return syncer::SyncError(); |
619 } | 680 } |
620 | 681 |
621 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( | 682 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
655 void GenericChangeProcessor::StartImpl() { | 716 void GenericChangeProcessor::StartImpl() { |
656 DCHECK(CalledOnValidThread()); | 717 DCHECK(CalledOnValidThread()); |
657 } | 718 } |
658 | 719 |
659 syncer::UserShare* GenericChangeProcessor::share_handle() const { | 720 syncer::UserShare* GenericChangeProcessor::share_handle() const { |
660 DCHECK(CalledOnValidThread()); | 721 DCHECK(CalledOnValidThread()); |
661 return share_handle_; | 722 return share_handle_; |
662 } | 723 } |
663 | 724 |
664 } // namespace browser_sync | 725 } // namespace browser_sync |
OLD | NEW |