Chromium Code Reviews| Index: chrome/browser/sync/engine/conflict_resolver.cc |
| diff --git a/chrome/browser/sync/engine/conflict_resolver.cc b/chrome/browser/sync/engine/conflict_resolver.cc |
| index e06d02d06ed4b4f153838f88c8f2d512ad29c884..91c3d46e3e3a40a657f96c9478de0a551cba4741 100644 |
| --- a/chrome/browser/sync/engine/conflict_resolver.cc |
| +++ b/chrome/browser/sync/engine/conflict_resolver.cc |
| @@ -12,10 +12,12 @@ |
| #include "base/metrics/histogram.h" |
| #include "chrome/browser/sync/engine/syncer.h" |
| #include "chrome/browser/sync/engine/syncer_util.h" |
| +#include "chrome/browser/sync/protocol/nigori_specifics.pb.h" |
| #include "chrome/browser/sync/protocol/service_constants.h" |
| #include "chrome/browser/sync/sessions/status_controller.h" |
| #include "chrome/browser/sync/syncable/directory_manager.h" |
| #include "chrome/browser/sync/syncable/syncable.h" |
| +#include "chrome/browser/sync/util/cryptographer.h" |
| using std::map; |
| using std::set; |
| @@ -43,6 +45,7 @@ enum SimpleConflictResolutions { |
| UNDELETE, // Resolved by undeleting local item. |
| IGNORE_ENCRYPTION, // Resolved by ignoring an encryption-only server |
| // change. TODO(zea): implement and use this. |
| + NIGORI_MERGE, // Resolved by merging nigori nodes. |
| CONFLICT_RESOLUTION_SIZE, |
| }; |
| @@ -78,6 +81,7 @@ void ConflictResolver::OverwriteServerChanges(WriteTransaction* trans, |
| ConflictResolver::ProcessSimpleConflictResult |
| ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans, |
| const Id& id, |
| + const Cryptographer* cryptographer, |
| StatusController* status) { |
| MutableEntry entry(trans, syncable::GET_BY_ID, id); |
| // Must be good as the entry won't have been cleaned up. |
| @@ -124,7 +128,40 @@ ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans, |
| entry.Get(syncable::SERVER_PARENT_ID); |
| bool entry_deleted = entry.Get(syncable::IS_DEL); |
| - if (!entry_deleted && name_matches && parent_matches) { |
| + // We manually merge nigori data. |
| + // TODO(zea): Find a better way of doing this. As it stands, we have to |
|
tim (not reviewing)
2011/12/20 17:54:05
Maybe move this comment down to the set_sync_tabs
Nicolas Zea
2011/12/20 19:54:10
Done.
|
| + // update this code whenever we add a new non-cryptographer related field to |
| + // the nigori node. |
| + if (entry.GetModelType() == syncable::NIGORI) { |
| + // Create a new set of specifics based on the server specifics (which |
| + // preserves their encryption keys). |
| + sync_pb::EntitySpecifics specifics = |
| + entry.Get(syncable::SERVER_SPECIFICS); |
| + sync_pb::NigoriSpecifics* nigori = |
| + specifics.MutableExtension(sync_pb::nigori); |
| + // Store the merged set of encrypted types (cryptographer->Update(..) will |
| + // have merged the local types already). |
| + cryptographer->UpdateNigoriFromEncryptedTypes(nigori); |
| + // The local set of keys is already merged with the server's set within |
| + // the cryptographer. If we don't have pending keys we can store the |
| + // merged set back immediately. Else we preserve the server keys and will |
| + // update the nigori when the user provides the pending passphrase via |
| + // SetPassphrase(..). |
| + if (cryptographer->is_ready()) { |
| + cryptographer->GetKeys(nigori->mutable_encrypted()); |
| + } |
| + if (entry.Get(syncable::SPECIFICS).GetExtension(sync_pb::nigori) |
| + .sync_tabs()) { |
| + nigori->set_sync_tabs(true); |
| + } |
| + entry.Put(syncable::SPECIFICS, specifics); |
| + DVLOG(1) << "Resovling simple conflict, merging nigori nodes: " << entry; |
| + status->increment_num_server_overwrites(); |
| + OverwriteServerChanges(trans, &entry); |
| + UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", |
| + NIGORI_MERGE, |
| + CONFLICT_RESOLUTION_SIZE); |
| + } else if (!entry_deleted && name_matches && parent_matches) { |
| // TODO(zea): We may prefer to choose the local changes over the server |
| // if we know the local changes happened before (or vice versa). |
| // See http://crbug.com/76596 |
| @@ -460,6 +497,7 @@ bool ConflictResolver::ResolveSimpleConflicts( |
| const ConflictProgress& progress, |
| sessions::StatusController* status) { |
| WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir); |
| + Cryptographer* cryptographer = dir.manager()->GetCryptographer(&trans); |
|
tim (not reviewing)
2011/12/20 17:54:05
Is manager() or the cryptographer really not avail
Nicolas Zea
2011/12/20 19:54:10
Neither the status controller nor the conflict pro
|
| bool forward_progress = false; |
| // First iterate over simple conflict items (those that belong to no set). |
| set<Id>::const_iterator conflicting_item_it; |
| @@ -472,7 +510,7 @@ bool ConflictResolver::ResolveSimpleConflicts( |
| if (item_set_it == progress.IdToConflictSetEnd() || |
| 0 == item_set_it->second) { |
| // We have a simple conflict. |
| - switch (ProcessSimpleConflict(&trans, id, status)) { |
| + switch (ProcessSimpleConflict(&trans, id, cryptographer, status)) { |
| case NO_SYNC_PROGRESS: |
| { |
| int conflict_count = (simple_conflict_count_map_[id] += 2); |