| 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 e673a78b279404593c0809e375308090bcc6496b..7f5869052cecc716e380b43a0f81b8750b3a5ffc 100644
|
| --- a/chrome/browser/sync/internal_api/write_node.cc
|
| +++ b/chrome/browser/sync/internal_api/write_node.cc
|
| @@ -38,6 +38,7 @@ bool WriteNode::UpdateEntryWithEncryption(
|
| syncable::MutableEntry* entry) {
|
| syncable::ModelType type = syncable::GetModelTypeFromSpecifics(new_specifics);
|
| DCHECK_GE(type, syncable::FIRST_REAL_MODEL_TYPE);
|
| + const sync_pb::EntitySpecifics& old_specifics = entry->Get(SPECIFICS);
|
| const syncable::ModelTypeSet encrypted_types =
|
| cryptographer->GetEncryptedTypes();
|
| sync_pb::EntitySpecifics generated_specifics;
|
| @@ -56,7 +57,18 @@ bool WriteNode::UpdateEntryWithEncryption(
|
| << " with content: "
|
| << info;
|
| }
|
| - syncable::AddDefaultExtensionValue(type, &generated_specifics);
|
| + // Only copy over the old specifics if it is of the right type and already
|
| + // encrypted. The first time we encrypt a node we start from scratch, hence
|
| + // removing all the unencrypted data, but from then on we only want to
|
| + // update the node if the data changes or the encryption key changes.
|
| + if (syncable::GetModelTypeFromSpecifics(old_specifics) == type &&
|
| + old_specifics.has_encrypted()) {
|
| + generated_specifics.CopyFrom(old_specifics);
|
| + } else {
|
| + syncable::AddDefaultExtensionValue(type, &generated_specifics);
|
| + }
|
| + // Does not change anything if underlying encrypted blob was already up
|
| + // to date and encrypted with the default key.
|
| if (!cryptographer->Encrypt(new_specifics,
|
| generated_specifics.mutable_encrypted())) {
|
| NOTREACHED() << "Could not encrypt data for node of type "
|
| @@ -65,21 +77,19 @@ bool WriteNode::UpdateEntryWithEncryption(
|
| }
|
| }
|
|
|
| - const sync_pb::EntitySpecifics& old_specifics = entry->Get(SPECIFICS);
|
| - if (AreSpecificsEqual(cryptographer, old_specifics, generated_specifics) &&
|
| - (entry->Get(syncable::NON_UNIQUE_NAME) == kEncryptedString ||
|
| - !generated_specifics.has_encrypted())) {
|
| - // Even if the data is the same but the old specifics are encrypted with an
|
| - // old key, we should go ahead and re-encrypt with the new key.
|
| - if ((!old_specifics.has_encrypted() &&
|
| - !generated_specifics.has_encrypted()) ||
|
| - cryptographer->CanDecryptUsingDefaultKey(old_specifics.encrypted())) {
|
| - DVLOG(2) << "Specifics of type " << syncable::ModelTypeToString(type)
|
| - << " already match, dropping change.";
|
| - return true;
|
| - }
|
| - // TODO(zea): Add some way to keep track of how often we're reencrypting
|
| - // because of a passphrase change.
|
| + // It's possible this entry was encrypted but didn't properly overwrite the
|
| + // non_unique_name (see crbug.com/96314).
|
| + bool encrypted_without_overwriting_name = (old_specifics.has_encrypted() &&
|
| + entry->Get(syncable::NON_UNIQUE_NAME) != kEncryptedString);
|
| +
|
| + // If we're encrypted but the name wasn't overwritten properly we still want
|
| + // to rewrite the entry, irrespective of whether the specifics match.
|
| + if (!encrypted_without_overwriting_name &&
|
| + old_specifics.SerializeAsString() ==
|
| + generated_specifics.SerializeAsString()) {
|
| + DVLOG(2) << "Specifics of type " << syncable::ModelTypeToString(type)
|
| + << " already match, dropping change.";
|
| + return true;
|
| }
|
|
|
| if (generated_specifics.has_encrypted()) {
|
| @@ -185,20 +195,6 @@ void WriteNode::SetPasswordSpecifics(
|
|
|
| Cryptographer* cryptographer = GetTransaction()->GetCryptographer();
|
|
|
| - // Idempotency check to prevent unnecessary syncing: if the plaintexts match
|
| - // and the old ciphertext is encrypted with the most current key, there's
|
| - // nothing to do here. Because each encryption is seeded with a different
|
| - // random value, checking for equivalence post-encryption doesn't suffice.
|
| - const sync_pb::EncryptedData& old_ciphertext =
|
| - GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::password).encrypted();
|
| - scoped_ptr<sync_pb::PasswordSpecificsData> old_plaintext(
|
| - DecryptPasswordSpecifics(GetEntry()->Get(SPECIFICS), cryptographer));
|
| - if (old_plaintext.get() &&
|
| - old_plaintext->SerializeAsString() == data.SerializeAsString() &&
|
| - cryptographer->CanDecryptUsingDefaultKey(old_ciphertext)) {
|
| - return;
|
| - }
|
| -
|
| sync_pb::PasswordSpecifics new_value;
|
| if (!cryptographer->Encrypt(data, new_value.mutable_encrypted())) {
|
| NOTREACHED() << "Failed to encrypt password, possibly due to sync node "
|
|
|