Index: components/sync_driver/generic_change_processor.cc |
diff --git a/components/sync_driver/generic_change_processor.cc b/components/sync_driver/generic_change_processor.cc |
index adc4c90ed42d96897330b9168588cea05beb58b3..49889a69c1b2234b94d27826d40e9fa9cbc76ca3 100644 |
--- a/components/sync_driver/generic_change_processor.cc |
+++ b/components/sync_driver/generic_change_processor.cc |
@@ -36,6 +36,27 @@ void SetNodeSpecifics(const sync_pb::EntitySpecifics& entity_specifics, |
} |
} |
+// Helper function to convert AttachmentId to AttachmentMetadataRecord. |
+sync_pb::AttachmentMetadataRecord AttachmentIdToRecord( |
+ const syncer::AttachmentId& attachment_id) { |
+ sync_pb::AttachmentMetadataRecord record; |
+ *record.mutable_id() = attachment_id.GetProto(); |
+ return record; |
+} |
+ |
+// Replace |write_nodes|'s attachment ids with |attachment_ids|. |
+void SetAttachmentMetadata(const syncer::AttachmentIdList& attachment_ids, |
+ syncer::WriteNode* write_node) { |
+ DCHECK(write_node); |
+ sync_pb::AttachmentMetadata attachment_metadata; |
+ std::transform( |
+ attachment_ids.begin(), |
+ attachment_ids.end(), |
+ RepeatedFieldBackInserter(attachment_metadata.mutable_record()), |
+ AttachmentIdToRecord); |
+ write_node->SetAttachmentMetadata(attachment_metadata); |
+} |
+ |
syncer::SyncData BuildRemoteSyncData( |
int64 sync_id, |
const syncer::BaseNode& read_node, |
@@ -319,12 +340,11 @@ syncer::SyncError LogLookupFailure( |
} |
} |
-syncer::SyncError AttemptDelete( |
- const syncer::SyncChange& change, |
- syncer::ModelType type, |
- const std::string& type_str, |
- syncer::WriteNode* node, |
- DataTypeErrorHandler* error_handler) { |
+syncer::SyncError AttemptDelete(const syncer::SyncChange& change, |
+ syncer::ModelType type, |
+ const std::string& type_str, |
+ syncer::WriteNode* node, |
+ DataTypeErrorHandler* error_handler) { |
DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE); |
if (change.sync_data().IsLocal()) { |
const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); |
@@ -368,12 +388,36 @@ syncer::SyncError AttemptDelete( |
return syncer::SyncError(); |
} |
+// A callback invoked on completion of AttachmentService::StoreAttachment. |
+void IgnoreStoreResult(const syncer::AttachmentService::StoreResult&) { |
+ // TODO(maniscalco): Here is where we're going to update the in-directory |
+ // entry to indicate that the attachments have been successfully stored on |
+ // disk. Why do we care? Because we might crash after persisting the |
+ // directory to disk, but before we have persisted its attachments, leaving us |
+ // with danging attachment ids. Having a flag that indicates we've stored the |
+ // entry will allow us to detect and filter entries with dangling attachment |
+ // ids (bug 368353). |
+} |
+ |
+void StoreAttachments(syncer::AttachmentService* attachment_service, |
+ const syncer::AttachmentList& attachments) { |
+ DCHECK(attachment_service); |
+ syncer::AttachmentService::StoreCallback ignore_store_result = |
+ base::Bind(&IgnoreStoreResult); |
+ attachment_service->StoreAttachments(attachments, ignore_store_result); |
+} |
+ |
} // namespace |
syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( |
const tracked_objects::Location& from_here, |
const syncer::SyncChangeList& list_of_changes) { |
DCHECK(CalledOnValidThread()); |
+ |
+ // Keep track of brand new attachments so we can persist them on this device |
+ // and upload them to the server. |
+ syncer::AttachmentList new_attachments; |
+ |
syncer::WriteTransaction trans(from_here, share_handle()); |
for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); |
@@ -391,20 +435,19 @@ syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( |
NOTREACHED(); |
return error; |
} |
- attachment_service_->OnSyncDataDelete(change.sync_data()); |
if (merge_result_.get()) { |
merge_result_->set_num_items_deleted( |
merge_result_->num_items_deleted() + 1); |
} |
} else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { |
- syncer::SyncError error = |
- HandleActionAdd(change, type_str, type, trans, &sync_node); |
+ syncer::SyncError error = HandleActionAdd( |
+ change, type_str, type, trans, &sync_node, &new_attachments); |
if (error.IsSet()) { |
return error; |
} |
} else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { |
- syncer::SyncError error = |
- HandleActionUpdate(change, type_str, type, trans, &sync_node); |
+ syncer::SyncError error = HandleActionUpdate( |
+ change, type_str, type, trans, &sync_node, &new_attachments); |
if (error.IsSet()) { |
return error; |
} |
@@ -422,6 +465,11 @@ syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( |
return error; |
} |
} |
+ |
+ if (!new_attachments.empty()) { |
+ StoreAttachments(attachment_service_.get(), new_attachments); |
+ } |
+ |
return syncer::SyncError(); |
} |
@@ -434,12 +482,14 @@ syncer::SyncError GenericChangeProcessor::HandleActionAdd( |
const std::string& type_str, |
const syncer::ModelType& type, |
const syncer::WriteTransaction& trans, |
- syncer::WriteNode* sync_node) { |
+ syncer::WriteNode* sync_node, |
+ syncer::AttachmentList* new_attachments) { |
// TODO(sync): Handle other types of creation (custom parents, folders, |
// etc.). |
syncer::ReadNode root_node(&trans); |
+ const syncer::SyncDataLocal sync_data_local(change.sync_data()); |
if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag( |
- change.sync_data().GetDataType())) != syncer::BaseNode::INIT_OK) { |
+ sync_data_local.GetDataType())) != syncer::BaseNode::INIT_OK) { |
syncer::SyncError error(FROM_HERE, |
syncer::SyncError::DATATYPE_ERROR, |
"Failed to look up root node for type " + type_str, |
@@ -452,9 +502,7 @@ syncer::SyncError GenericChangeProcessor::HandleActionAdd( |
} |
syncer::WriteNode::InitUniqueByCreationResult result = |
sync_node->InitUniqueByCreation( |
- change.sync_data().GetDataType(), |
- root_node, |
- syncer::SyncDataLocal(change.sync_data()).GetTag()); |
+ sync_data_local.GetDataType(), root_node, sync_data_local.GetTag()); |
if (result != syncer::WriteNode::INIT_SUCCESS) { |
std::string error_prefix = "Failed to create " + type_str + " node: " + |
change.location().ToString() + ", "; |
@@ -503,8 +551,18 @@ syncer::SyncError GenericChangeProcessor::HandleActionAdd( |
} |
} |
sync_node->SetTitle(change.sync_data().GetTitle()); |
- SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); |
- attachment_service_->OnSyncDataAdd(change.sync_data()); |
+ SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
+ |
+ syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); |
+ SetAttachmentMetadata(attachment_ids, sync_node); |
+ |
+ // Return any newly added attachments. |
+ const syncer::AttachmentList& local_attachments_for_upload = |
+ sync_data_local.GetLocalAttachmentsForUpload(); |
+ new_attachments->insert(new_attachments->end(), |
+ local_attachments_for_upload.begin(), |
+ local_attachments_for_upload.end()); |
+ |
if (merge_result_.get()) { |
merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); |
} |
@@ -519,12 +577,14 @@ syncer::SyncError GenericChangeProcessor::HandleActionUpdate( |
const std::string& type_str, |
const syncer::ModelType& type, |
const syncer::WriteTransaction& trans, |
- syncer::WriteNode* sync_node) { |
+ syncer::WriteNode* sync_node, |
+ syncer::AttachmentList* new_attachments) { |
// TODO(zea): consider having this logic for all possible changes? |
+ |
+ const syncer::SyncDataLocal sync_data_local(change.sync_data()); |
syncer::BaseNode::InitByLookupResult result = |
- sync_node->InitByClientTagLookup( |
- change.sync_data().GetDataType(), |
- syncer::SyncDataLocal(change.sync_data()).GetTag()); |
+ sync_node->InitByClientTagLookup(sync_data_local.GetDataType(), |
+ sync_data_local.GetTag()); |
if (result != syncer::BaseNode::INIT_OK) { |
std::string error_prefix = "Failed to load " + type_str + " node. " + |
change.location().ToString() + ", "; |
@@ -606,9 +666,16 @@ syncer::SyncError GenericChangeProcessor::HandleActionUpdate( |
} |
sync_node->SetTitle(change.sync_data().GetTitle()); |
- SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); |
- attachment_service_->OnSyncDataUpdate(sync_node->GetAttachmentIds(), |
- change.sync_data()); |
+ SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
+ SetAttachmentMetadata(sync_data_local.GetAttachmentIds(), sync_node); |
+ |
+ // Return any newly added attachments. |
+ const syncer::AttachmentList& local_attachments_for_upload = |
+ sync_data_local.GetLocalAttachmentsForUpload(); |
+ new_attachments->insert(new_attachments->end(), |
+ local_attachments_for_upload.begin(), |
+ local_attachments_for_upload.end()); |
+ |
if (merge_result_.get()) { |
merge_result_->set_num_items_modified(merge_result_->num_items_modified() + |
1); |