Index: chrome/browser/sync/internal_api/write_node.cc |
diff --git a/chrome/browser/sync/internal_api/write_node.cc b/chrome/browser/sync/internal_api/write_node.cc |
index 7f5869052cecc716e380b43a0f81b8750b3a5ffc..023061a2511c6ec1e42dd281bbb2e181af0afc82 100644 |
--- a/chrome/browser/sync/internal_api/write_node.cc |
+++ b/chrome/browser/sync/internal_api/write_node.cc |
@@ -195,15 +195,28 @@ void WriteNode::SetPasswordSpecifics( |
Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); |
- sync_pb::PasswordSpecifics new_value; |
- if (!cryptographer->Encrypt(data, new_value.mutable_encrypted())) { |
+ // We have to do the idempotency check here (vs in UpdateEntryWithEncryption) |
+ // because Passwords have their encrypted data within the PasswordSpecifics, |
+ // vs within the EntitySpecifics like all the other types. |
+ const sync_pb::EntitySpecifics& old_specifics = GetEntry()->Get(SPECIFICS); |
+ sync_pb::EntitySpecifics entity_specifics; |
+ // Copy over the old specifics if they exist. |
+ if (syncable::GetModelTypeFromSpecifics(old_specifics) == |
+ syncable::PASSWORDS) { |
+ entity_specifics.CopyFrom(old_specifics); |
+ } else { |
+ syncable::AddDefaultExtensionValue(syncable::PASSWORDS, |
+ &entity_specifics); |
+ } |
+ sync_pb::PasswordSpecifics* password_specifics = |
+ entity_specifics.MutableExtension(sync_pb::password); |
+ // This will only update password_specifics if the underlying unencrypted blob |
+ // was different from |data| or was not encrypted with the proper passphrase. |
+ if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { |
NOTREACHED() << "Failed to encrypt password, possibly due to sync node " |
<< "corruption"; |
return; |
} |
- |
- sync_pb::EntitySpecifics entity_specifics; |
- entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); |
SetEntitySpecifics(entity_specifics); |
} |