Chromium Code Reviews| Index: chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc |
| diff --git a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc |
| index 003622cea4621b11b04340040a0f284008c57774..26485121764a2d966cc996faf81400e4dcf2d1f1 100644 |
| --- a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc |
| +++ b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc |
| @@ -106,15 +106,6 @@ RemoteToLocalSyncer::~RemoteToLocalSyncer() { |
| void RemoteToLocalSyncer::RunPreflight(scoped_ptr<SyncTaskToken> token) { |
| token->InitializeTaskLog("Remote -> Local"); |
| - scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker); |
| - task_blocker->exclusive = true; |
| - SyncTaskManager::UpdateTaskBlocker( |
| - token.Pass(), task_blocker.Pass(), |
| - base::Bind(&RemoteToLocalSyncer::RunExclusive, |
| - weak_ptr_factory_.GetWeakPtr())); |
| -} |
| - |
| -void RemoteToLocalSyncer::RunExclusive(scoped_ptr<SyncTaskToken> token) { |
| if (!drive_service() || !metadata_database() || !remote_change_processor()) { |
| token->RecordLog("Context not ready."); |
| SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); |
| @@ -146,7 +137,11 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| NOTREACHED(); |
| } |
| token->RecordLog("Missing remote metadata case."); |
| - HandleMissingRemoteMetadata(token.Pass()); |
| + |
| + MoveToBackground( |
| + token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleMissingRemoteMetadata, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| @@ -183,7 +178,8 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| synced_details.title() != remote_details.title() || |
| remote_details.parent_folder_ids_size()) { |
| token->RecordLog("Sync-root deletion."); |
| - HandleSyncRootDeletion(token.Pass()); |
| + sync_root_deletion_ = true; |
| + SyncCompleted(token.Pass(), SYNC_STATUS_OK); |
| return; |
| } |
| token->RecordLog("Trivial sync-root change."); |
| @@ -194,10 +190,20 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| DCHECK_NE(dirty_tracker_->tracker_id(), |
| metadata_database()->GetSyncRootTrackerID()); |
| + if (!BuildFileSystemURL(metadata_database(), *dirty_tracker_, &url_)) { |
| + NOTREACHED(); |
| + SyncCompleted(token.Pass(), SYNC_STATUS_FAILED); |
| + return; |
| + } |
| + |
| + DCHECK(url_.is_valid()); |
| + |
| if (remote_details.missing()) { |
| if (!synced_details.missing()) { |
| token->RecordLog("Remote file deletion."); |
| - HandleDeletion(token.Pass()); |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleDeletion, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| @@ -238,9 +244,10 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| if (synced_details.title() != remote_details.title()) { |
| // Handle rename as deletion + addition. |
| token->RecordLog("Detected file rename."); |
| - Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, |
| - weak_ptr_factory_.GetWeakPtr(), |
| - base::Passed(&token))); |
| + |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleFileMove, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| DCHECK_EQ(synced_details.title(), remote_details.title()); |
| @@ -258,28 +265,35 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| if (!HasFolderAsParent(remote_details, parent_tracker.file_id())) { |
| // Handle reorganize as deletion + addition. |
| token->RecordLog("Detected file reorganize."); |
| - Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, |
| - weak_ptr_factory_.GetWeakPtr(), |
| - base::Passed(&token))); |
| + |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleFileMove, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| if (synced_details.file_kind() == FILE_KIND_FILE) { |
| if (synced_details.md5() != remote_details.md5()) { |
| token->RecordLog("Detected file content update."); |
| - HandleContentUpdate(token.Pass()); |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleContentUpdate, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| } else { |
| DCHECK_EQ(FILE_KIND_FOLDER, synced_details.file_kind()); |
| if (synced_details.missing()) { |
| token->RecordLog("Detected folder update."); |
| - HandleFolderUpdate(token.Pass()); |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::HandleFolderUpdate, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| if (dirty_tracker_->needs_folder_listing()) { |
| token->RecordLog("Needs listing folder."); |
| - ListFolderContent(token.Pass()); |
| + MoveToBackground(token.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::ListFolderContent, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| } |
| SyncCompleted(token.Pass(), SYNC_STATUS_OK); |
| @@ -290,6 +304,88 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { |
| SyncCompleted(token.Pass(), SYNC_STATUS_OK); |
| } |
| +void RemoteToLocalSyncer::MoveToBackground(scoped_ptr<SyncTaskToken> token, |
| + const Continuation& continuation) { |
| + DCHECK(dirty_tracker_); |
| + |
| + scoped_ptr<TaskBlocker> blocker(new TaskBlocker); |
| + blocker->app_id = dirty_tracker_->app_id(); |
| + if (url_.is_valid()) |
| + blocker->paths.push_back(url_.path()); |
| + blocker->file_ids.push_back(dirty_tracker_->file_id()); |
| + blocker->tracker_ids.push_back(dirty_tracker_->tracker_id()); |
| + |
| + SyncTaskManager::UpdateTaskBlocker( |
| + token.Pass(), blocker.Pass(), |
| + base::Bind(&RemoteToLocalSyncer::ContinueAsBackgroundTask, |
| + weak_ptr_factory_.GetWeakPtr(), continuation)); |
| +} |
| + |
| +void RemoteToLocalSyncer::ContinueAsBackgroundTask( |
| + const Continuation& continuation, |
| + scoped_ptr<SyncTaskToken> token) { |
| + DCHECK(dirty_tracker_); |
| + |
| + // The SyncTask runs as a background task beyond this point. |
| + // Not that any task can run between MoveToBackground() and |
| + // ContinueAsBackgroundTask(), so we need to make sure other tasks didn't |
| + // affect to the current RemoteToLocalSyncer task. |
| + // |
| + // - For LocalToRemoteSyncer, it may update or delete any of FileTracker and |
| + // FileMetadata. When it updates FileMetadata or FileDetais in FileTracker, |
|
nhiroki
2014/09/16 08:42:27
s/FileDetais/FileDetails/
tzik
2014/09/24 06:01:49
Done.
|
| + // it also updates |change_id|. So, ensure the target FileTracker and |
| + // FileMetadata exist and their |change_id|s are not updated. |
| + // - For ListChangesTask, it may update FileMetadata together with |change_id| |
| + // and may delete FileTracker. |
| + // - For UnininstallAppTask, it may delete FileMetadata and FileTracker. |
|
nhiroki
2014/09/16 08:42:27
s/UnininstallAppTask/UninstallAppTask/
tzik
2014/09/24 06:01:49
Done.
|
| + // Check if FileTracker still exists. |
| + // - For other RemoteToLocalSyncer, it may delete the FileTracker of parent. |
| + // Note that since RemoteToLocalSyncer demotes the target FileTracker first, |
| + // any other RemoteToLocalSyncer does not run for current |dirty_tracker_|. |
| + // - Others, SyncEngineInitializer and RegisterAppTask doesn't affect to |
| + |
| + FileTracker latest_dirty_tracker; |
| + if (!metadata_database()->FindTrackerByTrackerID( |
| + dirty_tracker_->tracker_id(), &latest_dirty_tracker) || |
| + dirty_tracker_->active() != latest_dirty_tracker.active() || |
| + !latest_dirty_tracker.dirty()) { |
| + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); |
| + return; |
| + } |
| + |
| + int64 current_change_id = kint64min; |
| + int64 latest_change_id = kint64min; |
| + if (dirty_tracker_->has_synced_details()) |
| + current_change_id = dirty_tracker_->synced_details().change_id(); |
| + if (latest_dirty_tracker.has_synced_details()) |
| + latest_change_id = latest_dirty_tracker.synced_details().change_id(); |
| + if (current_change_id != latest_change_id) { |
| + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); |
| + return; |
| + } |
| + |
| + FileMetadata latest_file_metadata; |
| + if (metadata_database()->FindFileByFileID(dirty_tracker_->file_id(), |
| + &latest_file_metadata)) { |
| + if (!remote_metadata_) { |
| + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); |
| + return; |
| + } |
| + |
| + if (remote_metadata_->details().change_id() != |
| + latest_file_metadata.details().change_id()) { |
|
nhiroki
2014/09/16 08:42:27
nit: You may need a 4-space indent.
tzik
2014/09/24 06:01:49
Done.
I introduced local variable for them.
|
| + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); |
| + return; |
| + } |
| + } else { |
| + if (remote_metadata_) { |
| + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); |
| + return; |
| + } |
| + } |
| + continuation.Run(token.Pass()); |
| +} |
| + |
| void RemoteToLocalSyncer::HandleMissingRemoteMetadata( |
| scoped_ptr<SyncTaskToken> token) { |
| DCHECK(dirty_tracker_); |
| @@ -444,12 +540,6 @@ void RemoteToLocalSyncer::DidPrepareForFolderUpdate( |
| CreateFolder(token.Pass()); |
| } |
| -void RemoteToLocalSyncer::HandleSyncRootDeletion( |
| - scoped_ptr<SyncTaskToken> token) { |
| - sync_root_deletion_ = true; |
| - SyncCompleted(token.Pass(), SYNC_STATUS_OK); |
| -} |
| - |
| void RemoteToLocalSyncer::HandleDeletion( |
| scoped_ptr<SyncTaskToken> token) { |
| DCHECK(dirty_tracker_); |
| @@ -467,6 +557,21 @@ void RemoteToLocalSyncer::HandleDeletion( |
| base::Passed(&token))); |
| } |
| +void RemoteToLocalSyncer::HandleFileMove(scoped_ptr<SyncTaskToken> token) { |
| + DCHECK(dirty_tracker_); |
| + DCHECK(dirty_tracker_->active()); |
| + DCHECK(!HasDisabledAppRoot(metadata_database(), *dirty_tracker_)); |
| + DCHECK(dirty_tracker_->has_synced_details()); |
| + |
| + DCHECK(remote_metadata_); |
| + DCHECK(remote_metadata_->has_details()); |
| + DCHECK(!remote_metadata_->details().missing()); |
| + |
| + Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + base::Passed(&token))); |
| +} |
| + |
| void RemoteToLocalSyncer::DidPrepareForDeletion( |
| scoped_ptr<SyncTaskToken> token, |
| SyncStatusCode status) { |
| @@ -639,9 +744,6 @@ void RemoteToLocalSyncer::FinalizeSync(scoped_ptr<SyncTaskToken> token, |
| } |
| void RemoteToLocalSyncer::Prepare(const SyncStatusCallback& callback) { |
| - bool should_success = BuildFileSystemURL( |
| - metadata_database(), *dirty_tracker_, &url_); |
| - DCHECK(should_success); |
| DCHECK(url_.is_valid()); |
| remote_change_processor()->PrepareForProcessRemoteChange( |
| url_, |