drive: Move task rerun logic from EntryUpdatePerformer to SyncClient

This logic should be applied for all sync tasks.

BUG=260538
TEST=unit_tests
[email protected]

Review URL: https://codereview.chromium.org/106303002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239138 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index e665f54d..b1ac1008 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -128,7 +128,7 @@
 
 }  // namespace
 
-SyncClient::SyncTask::SyncTask() : state(PENDING) {}
+SyncClient::SyncTask::SyncTask() : state(PENDING), should_run_again(false) {}
 SyncClient::SyncTask::~SyncTask() {}
 
 SyncClient::SyncClient(base::SequencedTaskRunner* blocking_task_runner,
@@ -288,9 +288,19 @@
                          const base::TimeDelta& delay) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  // If the same task is found, ignore this task.
-  if (tasks_.count(key))
+  SyncTasks::iterator it = tasks_.find(key);
+  if (it != tasks_.end()) {
+    switch (it->second.state) {
+      case PENDING:
+        // The same task will run, do nothing.
+        break;
+      case RUNNING:
+        // Something has changed since the task started. Schedule rerun.
+        it->second.should_run_again = true;
+        break;
+    }
     return;
+  }
 
   DCHECK_EQ(PENDING, task.state);
   tasks_[key] = task;
@@ -353,13 +363,32 @@
     AddFetchTask((*local_ids)[i]);
 }
 
+bool SyncClient::OnTaskComplete(SyncType type, const std::string& local_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  const SyncTasks::key_type key(type, local_id);
+  SyncTasks::iterator it = tasks_.find(key);
+  DCHECK(it != tasks_.end());
+
+  if (it->second.should_run_again) {
+    DVLOG(1) << "Running again: type = " << type << ", id = " << local_id;
+    it->second.should_run_again = false;
+    it->second.task.Run();
+    return false;
+  }
+
+  tasks_.erase(it);
+  return true;
+}
+
 void SyncClient::OnFetchFileComplete(const std::string& local_id,
                                      FileError error,
                                      const base::FilePath& local_path,
                                      scoped_ptr<ResourceEntry> entry) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  tasks_.erase(SyncTasks::key_type(FETCH, local_id));
+  if (!OnTaskComplete(FETCH, local_id))
+    return;
 
   if (error == FILE_ERROR_OK) {
     DVLOG(1) << "Fetched " << local_id << ": " << local_path.value();
@@ -390,7 +419,8 @@
                                       FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  tasks_.erase(SyncTasks::key_type(UPLOAD, local_id));
+  if (!OnTaskComplete(UPLOAD, local_id))
+    return;
 
   if (error == FILE_ERROR_OK) {
     DVLOG(1) << "Uploaded " << local_id;
@@ -419,7 +449,8 @@
                                   FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  tasks_.erase(SyncTasks::key_type(UPDATE, local_id));
+  if (!OnTaskComplete(UPDATE, local_id))
+    return;
 
   if (error == FILE_ERROR_OK) {
     DVLOG(1) << "Updated " << local_id;