Chromium Code Reviews| Index: sync/engine/sync_directory_update_handler.cc |
| diff --git a/sync/engine/sync_directory_update_handler.cc b/sync/engine/sync_directory_update_handler.cc |
| index 0d7953bb483dd1f4907fe59780fe05cb4c0847fa..f7046d8caa9f180bc0b5861105910fbe4c3fdd99 100644 |
| --- a/sync/engine/sync_directory_update_handler.cc |
| +++ b/sync/engine/sync_directory_update_handler.cc |
| @@ -4,19 +4,25 @@ |
| #include "sync/engine/sync_directory_update_handler.h" |
| +#include "sync/engine/conflict_resolver.h" |
| #include "sync/engine/process_updates_util.h" |
| +#include "sync/engine/update_applicator.h" |
| #include "sync/sessions/status_controller.h" |
| #include "sync/syncable/directory.h" |
| #include "sync/syncable/syncable_model_neutral_write_transaction.h" |
| +#include "sync/syncable/syncable_write_transaction.h" |
| namespace syncer { |
| using syncable::SYNCER; |
| SyncDirectoryUpdateHandler::SyncDirectoryUpdateHandler( |
| - syncable::Directory* dir, ModelType type) |
| + syncable::Directory* dir, |
| + ModelType type, |
| + scoped_refptr<ModelSafeWorker> worker) |
| : dir_(dir), |
| - type_(type) {} |
| + type_(type), |
| + worker_(worker) {} |
| SyncDirectoryUpdateHandler::~SyncDirectoryUpdateHandler() {} |
| @@ -34,6 +40,92 @@ void SyncDirectoryUpdateHandler::ProcessGetUpdatesResponse( |
| UpdateProgressMarker(progress_marker); |
| } |
| +void SyncDirectoryUpdateHandler::ApplyUpdates( |
| + sessions::StatusController* status) { |
| + if (IsControlType(type_)) { |
| + return; // We don't process control types here. |
|
Nicolas Zea
2013/11/19 22:45:26
What's the plan for control types? Do they not hav
rlarocque
2013/11/21 18:28:47
No, they do have SyncDirectoryUpdateHandlers. Tha
|
| + } |
| + |
| + if (!dir_->TypeHasUnappliedUpdates(type_)) { |
| + return; // No work to do. Skip this type. |
| + } |
| + |
| + WorkCallback c = base::Bind( |
| + &SyncDirectoryUpdateHandler::ApplyUpdatesImpl, |
| + // We wait until the callback is executed. So it is safe to use |
| + // unretained. |
| + base::Unretained(this), |
| + base::Unretained(status)); |
| + worker_->DoWorkAndWaitUntilDone(c); |
| +} |
| + |
| +SyncerError SyncDirectoryUpdateHandler::ApplyUpdatesImpl( |
| + sessions::StatusController* status) { |
| + syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir_); |
| + |
| + std::vector<int64> handles; |
| + dir_->GetUnappliedUpdateMetaHandles( |
| + &trans, |
| + FullModelTypeSet(type_), |
| + &handles); |
| + |
| + // First set of update application passes. |
| + UpdateApplicator applicator(dir_->GetCryptographer(&trans)); |
| + applicator.AttemptApplications(&trans, handles); |
| + status->increment_num_updates_applied_by(applicator.updates_applied()); |
| + status->increment_num_hierarchy_conflicts_by( |
| + applicator.hierarchy_conflicts()); |
| + status->increment_num_encryption_conflicts_by( |
| + applicator.encryption_conflicts()); |
| + |
| + if (applicator.simple_conflict_ids().size() != 0) { |
| + // Resolve the simple conflicts we just detected. |
| + ConflictResolver resolver; |
| + resolver.ResolveConflicts(&trans, |
| + dir_->GetCryptographer(&trans), |
| + applicator.simple_conflict_ids(), |
| + status); |
| + |
| + // Conflict resolution sometimes results in more updates to apply. |
| + handles.clear(); |
| + dir_->GetUnappliedUpdateMetaHandles( |
| + &trans, |
| + FullModelTypeSet(type_), |
| + &handles); |
| + |
| + UpdateApplicator conflict_applicator(dir_->GetCryptographer(&trans)); |
| + conflict_applicator.AttemptApplications(&trans, handles); |
| + |
| + // We count the number of updates from both applicator passes. |
| + status->increment_num_updates_applied_by( |
| + conflict_applicator.updates_applied()); |
| + |
| + // Encryption conflicts should remain unchanged by the resolution of simple |
| + // conflicts. Those can only be solved by updating our nigori key bag. |
| + DCHECK_EQ(conflict_applicator.encryption_conflicts(), |
| + applicator.encryption_conflicts()); |
| + |
| + // Hierarchy conflicts should also remain unchanged, for reasons that are |
| + // more subtle. Hierarchy conflicts exist when the application of a pending |
| + // update from the server would make the local folder hierarchy |
| + // inconsistent. The resolution of simple conflicts could never affect the |
| + // hierarchy conflicting item directly, because hierarchy conflicts are not |
| + // processed by the conflict resolver. It could, in theory, modify the |
| + // local hierarchy on which hierarchy conflict detection depends. However, |
| + // the conflict resolution algorithm currently in use does not allow this. |
| + DCHECK_EQ(conflict_applicator.hierarchy_conflicts(), |
| + applicator.hierarchy_conflicts()); |
| + |
| + // There should be no simple conflicts remaining. We know this because the |
| + // resolver should have resolved all the conflicts we detected last time |
| + // and, by the two previous assertions, that no conflicts have been |
| + // downgraded from encryption or hierarchy down to simple. |
| + DCHECK(conflict_applicator.simple_conflict_ids().empty()); |
| + } |
| + |
| + return SYNCER_OK; |
| +} |
| + |
| void SyncDirectoryUpdateHandler::UpdateSyncEntities( |
| syncable::ModelNeutralWriteTransaction* trans, |
| const SyncEntityList& applicable_updates, |