Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(601)

Unified Diff: chrome/browser/sync/engine/syncer_util.cc

Issue 8770032: [Sync] Implement encryption-aware conflict resolution. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix test Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/engine/syncer_util.cc
diff --git a/chrome/browser/sync/engine/syncer_util.cc b/chrome/browser/sync/engine/syncer_util.cc
index 20391686a6998a67428369181bd147711da5f52f..bf1456e662da5ebf12deedafce8c683dbf9486d9 100644
--- a/chrome/browser/sync/engine/syncer_util.cc
+++ b/chrome/browser/sync/engine/syncer_util.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/location.h"
+#include "base/metrics/histogram.h"
#include "chrome/browser/sync/engine/conflict_resolver.h"
#include "chrome/browser/sync/engine/nigori_util.h"
#include "chrome/browser/sync/engine/syncer_proto_util.h"
@@ -23,6 +24,7 @@
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/syncable/syncable_changes_version.h"
+#include "chrome/browser/sync/util/cryptographer.h"
#include "chrome/browser/sync/util/time.h"
using syncable::BASE_VERSION;
@@ -33,6 +35,7 @@ using syncable::CREATE_NEW_UPDATE_ITEM;
using syncable::CTIME;
using syncable::Directory;
using syncable::Entry;
+using syncable::GetModelTypeFromSpecifics;
using syncable::GET_BY_HANDLE;
using syncable::GET_BY_ID;
using syncable::ID;
@@ -41,11 +44,13 @@ using syncable::IS_DIR;
using syncable::IS_UNAPPLIED_UPDATE;
using syncable::IS_UNSYNCED;
using syncable::Id;
+using syncable::IsRealDataType;
using syncable::META_HANDLE;
using syncable::MTIME;
using syncable::MutableEntry;
using syncable::NEXT_ID;
using syncable::NON_UNIQUE_NAME;
+using syncable::BASE_SERVER_SPECIFICS;
using syncable::PARENT_ID;
using syncable::PREV_ID;
using syncable::ReadTransaction;
@@ -301,6 +306,33 @@ UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry(
}
}
+ // Only apply updates that we can decrypt. If we can't decrypt the update, it
+ // is likely because the passphrase has not arrived yet. Because the
+ // passphrase may not arrive within this GetUpdates, we can't just return
+ // conflict, else we try to perform normal conflict resolution prematurely or
+ // the syncer may get stuck. As such, we return CONFLICT_ENCRYPTION, which is
+ // treated as a non-blocking conflict. See the description in syncer_types.h.
+ // This prevents any unsynced changes from commiting and postpones conflict
+ // resolution until all data can be decrypted.
+ if (specifics.has_encrypted() &&
+ !cryptographer->CanDecrypt(specifics.encrypted())) {
+ // We can't decrypt this node yet.
+ DVLOG(1) << "Received an undecryptable "
+ << syncable::ModelTypeToString(entry->GetServerModelType())
+ << " update, returning encryption_conflict.";
+ return CONFLICT_ENCRYPTION;
+ } else if (specifics.HasExtension(sync_pb::password) &&
+ entry->Get(UNIQUE_SERVER_TAG).empty()) {
+ // Passwords use their own legacy encryption scheme.
+ const sync_pb::PasswordSpecifics& password =
+ specifics.GetExtension(sync_pb::password);
+ if (!cryptographer->CanDecrypt(password.encrypted())) {
+ DVLOG(1) << "Received an undecryptable password update, returning "
+ << "encryption_conflict.";
+ return CONFLICT_ENCRYPTION;
+ }
+ }
+
if (entry->Get(IS_UNSYNCED)) {
DVLOG(1) << "Skipping update, returning conflict for: " << id
<< " ; it's unsynced.";
@@ -336,39 +368,14 @@ UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry(
}
}
- // Only apply updates that we can decrypt. If we can't decrypt the update, it
- // is likely because the passphrase has not arrived yet. Because the
- // passphrase may not arrive within this GetUpdates, we can't just return
- // conflict, else the syncer gets stuck. As such, we return
- // CONFLICT_ENCRYPTION, which is treated as a non-blocking conflict. See the
- // description in syncer_types.h.
- if (specifics.has_encrypted() &&
- !cryptographer->CanDecrypt(specifics.encrypted())) {
- // We can't decrypt this node yet.
- DVLOG(1) << "Received an undecryptable "
+ if (specifics.has_encrypted()) {
+ DVLOG(2) << "Received a decryptable "
<< syncable::ModelTypeToString(entry->GetServerModelType())
- << " update, returning encryption_conflict.";
- return CONFLICT_ENCRYPTION;
- } else if (specifics.HasExtension(sync_pb::password) &&
- entry->Get(UNIQUE_SERVER_TAG).empty()) {
- // Passwords use their own legacy encryption scheme.
- const sync_pb::PasswordSpecifics& password =
- specifics.GetExtension(sync_pb::password);
- if (!cryptographer->CanDecrypt(password.encrypted())) {
- DVLOG(1) << "Received an undecryptable password update, returning "
- << "encryption_conflict.";
- return CONFLICT_ENCRYPTION;
- }
+ << " update, applying normally.";
} else {
- if (specifics.has_encrypted()) {
- DVLOG(2) << "Received a decryptable "
- << syncable::ModelTypeToString(entry->GetServerModelType())
- << " update, applying normally.";
- } else {
- DVLOG(2) << "Received an unencrypted "
- << syncable::ModelTypeToString(entry->GetServerModelType())
- << " update, applying normally.";
- }
+ DVLOG(2) << "Received an unencrypted "
+ << syncable::ModelTypeToString(entry->GetServerModelType())
+ << " update, applying normally.";
}
SyncerUtil::UpdateLocalDataFromServerData(trans, entry);
@@ -475,7 +482,7 @@ void SyncerUtil::UpdateServerFieldsFromUpdate(
// static
void SyncerUtil::CreateNewEntry(syncable::WriteTransaction *trans,
const syncable::Id& id) {
- syncable::MutableEntry entry(trans, syncable::GET_BY_ID, id);
+ syncable::MutableEntry entry(trans, GET_BY_ID, id);
if (!entry.good()) {
syncable::MutableEntry new_entry(trans, syncable::CREATE_NEW_UPDATE_ITEM,
id);
@@ -510,6 +517,8 @@ void SyncerUtil::UpdateLocalDataFromServerData(
DVLOG(2) << "Updating entry : " << *entry;
// Start by setting the properties that determine the model_type.
entry->Put(SPECIFICS, entry->Get(SERVER_SPECIFICS));
+ // Clear the previous server specifics now that we're applying successfully.
+ entry->Put(BASE_SERVER_SPECIFICS, sync_pb::EntitySpecifics());
entry->Put(IS_DIR, entry->Get(SERVER_IS_DIR));
// This strange dance around the IS_DEL flag avoids problems when setting
// the name.
« no previous file with comments | « chrome/browser/sync/engine/syncer_unittest.cc ('k') | chrome/browser/sync/syncable/directory_backing_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698