Index: sync/internal_api/shared_model_type_processor.cc |
diff --git a/sync/internal_api/shared_model_type_processor.cc b/sync/internal_api/shared_model_type_processor.cc |
index 64d551af0e6341cea1fdb5ab7a52598a5c5ad77f..b8fe4721e5bf627c6fdec235d07b0d5fc8effa79 100644 |
--- a/sync/internal_api/shared_model_type_processor.cc |
+++ b/sync/internal_api/shared_model_type_processor.cc |
@@ -237,7 +237,7 @@ void SharedModelTypeProcessor::Put(const std::string& tag, |
data->creation_time = data->modification_time; |
} |
entity = CreateEntity(tag, *data); |
- } else if (entity->MatchesSpecificsHash(data->specifics)) { |
+ } else if (entity->MatchesData(*data)) { |
// Ignore changes that don't actually change anything. |
return; |
} |
@@ -316,8 +316,7 @@ void SharedModelTypeProcessor::OnCommitCompleted( |
continue; |
} |
- entity->ReceiveCommitResponse(data.id, data.sequence_number, |
- data.response_version); |
+ entity->ReceiveCommitResponse(data); |
if (entity->CanClearMetadata()) { |
change_list->ClearMetadata(entity->client_tag()); |
@@ -419,7 +418,7 @@ ProcessorEntityTracker* SharedModelTypeProcessor::ProcessUpdate( |
DCHECK(!entity->metadata().is_deleted()); |
entity_changes->push_back(EntityChange::CreateDelete(entity->client_tag())); |
entity->RecordAcceptedUpdate(update); |
- } else if (!entity->MatchesSpecificsHash(data.specifics)) { |
+ } else if (!entity->MatchesData(data)) { |
// Specifics have changed, so update the service. |
entity_changes->push_back( |
EntityChange::CreateUpdate(entity->client_tag(), update.entity)); |
@@ -452,29 +451,48 @@ ConflictResolution::Type SharedModelTypeProcessor::ResolveConflict( |
const UpdateResponseData& update, |
ProcessorEntityTracker* entity, |
EntityChangeList* changes) { |
- const EntityData& data = update.entity.value(); |
- |
- if (entity->MatchesData(data)) { |
- // Record the update and squash the pending commit. |
- entity->RecordForcedUpdate(update); |
- return ConflictResolution::CHANGES_MATCH; |
+ const EntityData& remote_data = update.entity.value(); |
+ |
+ ConflictResolution::Type resolution_type = ConflictResolution::TYPE_SIZE; |
+ std::unique_ptr<EntityData> new_data; |
+ |
+ // Determine the type of resolution. |
+ if (entity->MatchesData(remote_data)) { |
+ // The changes are identical so there isn't a real conflict. |
+ resolution_type = ConflictResolution::CHANGES_MATCH; |
+ } else if (entity->RequiresCommitData() || |
+ entity->MatchesBaseData(entity->commit_data().value())) { |
+ // If commit data needs to be loaded at this point, it can only be due to a |
+ // re-encryption request. If the commit data matches the base data, it also |
+ // must be a re-encryption request. Either way there's no real local change |
+ // and the remote data should win. |
+ resolution_type = ConflictResolution::IGNORE_LOCAL_ENCRYPTION; |
+ } else if (entity->MatchesBaseData(remote_data)) { |
+ // The remote data isn't actually changing from the last remote data that |
+ // was seen, so it must have been a re-encryption and can be ignored. |
+ resolution_type = ConflictResolution::IGNORE_REMOTE_ENCRYPTION; |
+ } else { |
+ // There's a real data conflict here; let the service resolve it. |
+ ConflictResolution resolution = |
+ service_->ResolveConflict(entity->commit_data().value(), remote_data); |
+ resolution_type = resolution.type(); |
+ new_data = resolution.ExtractData(); |
} |
- // If commit data needs to be loaded at this point, it can only be due to a |
- // re-encryption request, which means there's no actual local change and the |
- // remote version should win. Otherwise there's a real data conflict here; let |
- // the service resolve it. |
- ConflictResolution resolution = |
- entity->RequiresCommitData() |
- ? ConflictResolution::UseRemote() |
- : service_->ResolveConflict(entity->commit_data().value(), data); |
- switch (resolution.type()) { |
+ // Apply the resolution. |
+ switch (resolution_type) { |
+ case ConflictResolution::CHANGES_MATCH: |
+ // Record the update and squash the pending commit. |
+ entity->RecordForcedUpdate(update); |
+ break; |
case ConflictResolution::USE_LOCAL: |
+ case ConflictResolution::IGNORE_REMOTE_ENCRYPTION: |
// Record that we received the update from the server but leave the |
// pending commit intact. |
entity->RecordIgnoredUpdate(update); |
break; |
case ConflictResolution::USE_REMOTE: |
+ case ConflictResolution::IGNORE_LOCAL_ENCRYPTION: |
// Squash the pending commit. |
entity->RecordForcedUpdate(update); |
// Update client data to match server. |
@@ -485,17 +503,18 @@ ConflictResolution::Type SharedModelTypeProcessor::ResolveConflict( |
// Record that we received the update. |
entity->RecordIgnoredUpdate(update); |
// Make a new pending commit to update the server. |
- entity->MakeLocalChange(resolution.ExtractData()); |
+ entity->MakeLocalChange(std::move(new_data)); |
// Update the client with the new entity. |
changes->push_back(EntityChange::CreateUpdate(entity->client_tag(), |
entity->commit_data())); |
break; |
- case ConflictResolution::CHANGES_MATCH: |
case ConflictResolution::TYPE_SIZE: |
NOTREACHED(); |
break; |
} |
- return resolution.type(); |
+ DCHECK(!new_data); |
+ |
+ return resolution_type; |
} |
void SharedModelTypeProcessor::RecommitAllForEncryption( |