Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / sync_worker.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync_file_system/drive_backend/sync_worker.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "chrome/browser/drive/drive_service_interface.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h"
13 #include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
15 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
16 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h"
17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
18 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
19 #include "chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.h"
20 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
22 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
23 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
24 #include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h"
25 #include "chrome/browser/sync_file_system/logger.h"
26 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
27 #include "storage/common/fileapi/file_system_util.h"
28
29 namespace sync_file_system {
30
31 class RemoteChangeProcessor;
32
33 namespace drive_backend {
34
35 namespace {
36
37 void EmptyStatusCallback(SyncStatusCode status) {}
38
39 void InvokeIdleCallback(const base::Closure& idle_callback,
40                         const SyncStatusCallback& callback) {
41   idle_callback.Run();
42   callback.Run(SYNC_STATUS_OK);
43 }
44
45 }  // namespace
46
47 SyncWorker::SyncWorker(
48     const base::FilePath& base_dir,
49     const base::WeakPtr<ExtensionServiceInterface>& extension_service,
50     leveldb::Env* env_override)
51     : base_dir_(base_dir),
52       env_override_(env_override),
53       service_state_(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE),
54       should_check_conflict_(true),
55       should_check_remote_change_(true),
56       listing_remote_changes_(false),
57       sync_enabled_(false),
58       extension_service_(extension_service),
59       weak_ptr_factory_(this) {
60   sequence_checker_.DetachFromSequence();
61   DCHECK(base_dir_.IsAbsolute());
62 }
63
64 SyncWorker::~SyncWorker() {
65   observers_.Clear();
66 }
67
68 void SyncWorker::Initialize(scoped_ptr<SyncEngineContext> context) {
69   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
70   DCHECK(!task_manager_);
71
72   context_ = context.Pass();
73
74   task_manager_.reset(new SyncTaskManager(
75       weak_ptr_factory_.GetWeakPtr(), 0 /* maximum_background_task */,
76       context_->GetWorkerTaskRunner()));
77   task_manager_->Initialize(SYNC_STATUS_OK);
78
79   PostInitializeTask();
80 }
81
82 void SyncWorker::RegisterOrigin(
83     const GURL& origin,
84     const SyncStatusCallback& callback) {
85   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
86
87   if (!GetMetadataDatabase())
88     PostInitializeTask();
89
90   scoped_ptr<RegisterAppTask> task(
91       new RegisterAppTask(context_.get(), origin.host()));
92   if (task->CanFinishImmediately()) {
93     callback.Run(SYNC_STATUS_OK);
94     return;
95   }
96
97   task_manager_->ScheduleSyncTask(
98       FROM_HERE, task.Pass(), SyncTaskManager::PRIORITY_HIGH, callback);
99 }
100
101 void SyncWorker::EnableOrigin(
102     const GURL& origin,
103     const SyncStatusCallback& callback) {
104   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
105
106   task_manager_->ScheduleTask(
107       FROM_HERE,
108       base::Bind(&SyncWorker::DoEnableApp,
109                  weak_ptr_factory_.GetWeakPtr(),
110                  origin.host()),
111       SyncTaskManager::PRIORITY_HIGH,
112       callback);
113 }
114
115 void SyncWorker::DisableOrigin(
116     const GURL& origin,
117     const SyncStatusCallback& callback) {
118   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
119
120   task_manager_->ScheduleTask(
121       FROM_HERE,
122       base::Bind(&SyncWorker::DoDisableApp,
123                  weak_ptr_factory_.GetWeakPtr(),
124                  origin.host()),
125       SyncTaskManager::PRIORITY_HIGH,
126       callback);
127 }
128
129 void SyncWorker::UninstallOrigin(
130     const GURL& origin,
131     RemoteFileSyncService::UninstallFlag flag,
132     const SyncStatusCallback& callback) {
133   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
134
135   task_manager_->ScheduleSyncTask(
136       FROM_HERE,
137       scoped_ptr<SyncTask>(
138           new UninstallAppTask(context_.get(), origin.host(), flag)),
139       SyncTaskManager::PRIORITY_HIGH,
140       callback);
141 }
142
143 void SyncWorker::ProcessRemoteChange(const SyncFileCallback& callback) {
144   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
145
146   RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(context_.get());
147   task_manager_->ScheduleSyncTask(
148       FROM_HERE,
149       scoped_ptr<SyncTask>(syncer),
150       SyncTaskManager::PRIORITY_MED,
151       base::Bind(&SyncWorker::DidProcessRemoteChange,
152                  weak_ptr_factory_.GetWeakPtr(),
153                  syncer,
154                  callback));
155 }
156
157 void SyncWorker::SetRemoteChangeProcessor(
158     RemoteChangeProcessorOnWorker* remote_change_processor_on_worker) {
159   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
160
161   context_->SetRemoteChangeProcessor(remote_change_processor_on_worker);
162 }
163
164 RemoteServiceState SyncWorker::GetCurrentState() const {
165   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
166
167   if (!sync_enabled_)
168     return REMOTE_SERVICE_DISABLED;
169   return service_state_;
170 }
171
172 void SyncWorker::GetOriginStatusMap(
173     const RemoteFileSyncService::StatusMapCallback& callback) {
174   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
175
176   if (!GetMetadataDatabase())
177     return;
178
179   std::vector<std::string> app_ids;
180   GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
181
182   scoped_ptr<RemoteFileSyncService::OriginStatusMap>
183       status_map(new RemoteFileSyncService::OriginStatusMap);
184   for (std::vector<std::string>::const_iterator itr = app_ids.begin();
185        itr != app_ids.end(); ++itr) {
186     const std::string& app_id = *itr;
187     GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
188     (*status_map)[origin] =
189         GetMetadataDatabase()->IsAppEnabled(app_id) ? "Enabled" : "Disabled";
190   }
191
192   callback.Run(status_map.Pass());
193 }
194
195 scoped_ptr<base::ListValue> SyncWorker::DumpFiles(const GURL& origin) {
196   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
197
198   if (!GetMetadataDatabase())
199     return scoped_ptr<base::ListValue>();
200   return GetMetadataDatabase()->DumpFiles(origin.host());
201 }
202
203 scoped_ptr<base::ListValue> SyncWorker::DumpDatabase() {
204   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
205
206   if (!GetMetadataDatabase())
207     return scoped_ptr<base::ListValue>();
208   return GetMetadataDatabase()->DumpDatabase();
209 }
210
211 void SyncWorker::SetSyncEnabled(bool enabled) {
212   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
213
214   if (sync_enabled_ == enabled)
215     return;
216
217   RemoteServiceState old_state = GetCurrentState();
218   sync_enabled_ = enabled;
219   if (old_state == GetCurrentState())
220     return;
221
222   FOR_EACH_OBSERVER(
223       Observer,
224       observers_,
225       UpdateServiceState(
226           GetCurrentState(),
227           enabled ? "Sync is enabled" : "Sync is disabled"));
228 }
229
230 void SyncWorker::PromoteDemotedChanges(const base::Closure& callback) {
231   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
232
233   MetadataDatabase* metadata_db = GetMetadataDatabase();
234   if (metadata_db && metadata_db->HasDemotedDirtyTracker()) {
235     metadata_db->PromoteDemotedTrackers();
236     FOR_EACH_OBSERVER(
237         Observer,
238         observers_,
239         OnPendingFileListUpdated(metadata_db->CountDirtyTracker()));
240   }
241   callback.Run();
242 }
243
244 void SyncWorker::ApplyLocalChange(const FileChange& local_change,
245                                   const base::FilePath& local_path,
246                                   const SyncFileMetadata& local_metadata,
247                                   const storage::FileSystemURL& url,
248                                   const SyncStatusCallback& callback) {
249   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
250
251   LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer(
252       context_.get(), local_metadata, local_change, local_path, url);
253   task_manager_->ScheduleSyncTask(
254       FROM_HERE,
255       scoped_ptr<SyncTask>(syncer),
256       SyncTaskManager::PRIORITY_MED,
257       base::Bind(&SyncWorker::DidApplyLocalChange,
258                  weak_ptr_factory_.GetWeakPtr(),
259                  syncer,
260                  callback));
261 }
262
263 void SyncWorker::MaybeScheduleNextTask() {
264   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
265
266   if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
267     return;
268
269   // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated.
270   // TODO(tzik): Add an interface to get the number of dirty trackers to
271   // MetadataDatabase.
272
273   if (MaybeStartFetchChanges())
274     return;
275
276   if (!call_on_idle_callback_.is_null()) {
277     base::Closure callback = call_on_idle_callback_;
278     call_on_idle_callback_.Reset();
279     callback.Run();
280   }
281 }
282
283 void SyncWorker::NotifyLastOperationStatus(
284     SyncStatusCode status,
285     bool used_network) {
286   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
287
288   UpdateServiceStateFromSyncStatusCode(status, used_network);
289
290   if (GetMetadataDatabase()) {
291     FOR_EACH_OBSERVER(
292         Observer, observers_,
293         OnPendingFileListUpdated(GetMetadataDatabase()->CountDirtyTracker()));
294   }
295 }
296
297 void SyncWorker::RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) {
298   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
299
300   context_->GetUITaskRunner()->PostTask(
301       FROM_HERE,
302       base::Bind(&TaskLogger::RecordLog,
303                  context_->GetTaskLogger(),
304                  base::Passed(&task_log)));
305 }
306
307 void SyncWorker::ActivateService(RemoteServiceState service_state,
308                                  const std::string& description) {
309   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
310   UpdateServiceState(service_state, description);
311   if (!GetMetadataDatabase()) {
312     PostInitializeTask();
313     return;
314   }
315
316   should_check_remote_change_ = true;
317   MaybeScheduleNextTask();
318 }
319
320 void SyncWorker::DeactivateService(const std::string& description) {
321   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
322   UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, description);
323 }
324
325 void SyncWorker::DetachFromSequence() {
326   task_manager_->DetachFromSequence();
327   context_->DetachFromSequence();
328   sequence_checker_.DetachFromSequence();
329 }
330
331 void SyncWorker::AddObserver(Observer* observer) {
332   observers_.AddObserver(observer);
333 }
334
335 void SyncWorker::DoDisableApp(const std::string& app_id,
336                               const SyncStatusCallback& callback) {
337   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
338
339   if (!GetMetadataDatabase()) {
340     callback.Run(SYNC_STATUS_OK);
341     return;
342   }
343
344   SyncStatusCode status = GetMetadataDatabase()->DisableApp(app_id);
345   callback.Run(status);
346 }
347
348 void SyncWorker::DoEnableApp(const std::string& app_id,
349                              const SyncStatusCallback& callback) {
350   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
351
352   if (!GetMetadataDatabase()) {
353     callback.Run(SYNC_STATUS_OK);
354     return;
355   }
356
357   SyncStatusCode status = GetMetadataDatabase()->EnableApp(app_id);
358   callback.Run(status);
359 }
360
361 void SyncWorker::PostInitializeTask() {
362   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
363   DCHECK(!GetMetadataDatabase());
364
365   // This initializer task may not run if MetadataDatabase in context_ is
366   // already initialized when it runs.
367   SyncEngineInitializer* initializer =
368       new SyncEngineInitializer(context_.get(),
369                                 base_dir_.Append(kDatabaseName),
370                                 env_override_);
371   task_manager_->ScheduleSyncTask(
372       FROM_HERE,
373       scoped_ptr<SyncTask>(initializer),
374       SyncTaskManager::PRIORITY_HIGH,
375       base::Bind(&SyncWorker::DidInitialize,
376                  weak_ptr_factory_.GetWeakPtr(),
377                  initializer));
378 }
379
380 void SyncWorker::DidInitialize(SyncEngineInitializer* initializer,
381                                SyncStatusCode status) {
382   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
383
384   if (status == SYNC_STATUS_ACCESS_FORBIDDEN) {
385     UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN, "Access forbidden");
386     return;
387   }
388   if (status != SYNC_STATUS_OK) {
389     UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
390                        "Could not initialize remote service");
391     return;
392   }
393
394   scoped_ptr<MetadataDatabase> metadata_database =
395       initializer->PassMetadataDatabase();
396   if (metadata_database) {
397     context_->SetMetadataDatabase(metadata_database.Pass());
398     return;
399   }
400
401   UpdateServiceState(REMOTE_SERVICE_OK, std::string());
402   UpdateRegisteredApps();
403 }
404
405 void SyncWorker::UpdateRegisteredApps() {
406   MetadataDatabase* metadata_db = GetMetadataDatabase();
407   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
408   DCHECK(metadata_db);
409
410   scoped_ptr<std::vector<std::string> > app_ids(new std::vector<std::string>);
411   metadata_db->GetRegisteredAppIDs(app_ids.get());
412
413   AppStatusMap* app_status = new AppStatusMap;
414   base::Closure callback =
415       base::Bind(&SyncWorker::DidQueryAppStatus,
416                  weak_ptr_factory_.GetWeakPtr(),
417                  base::Owned(app_status));
418
419   context_->GetUITaskRunner()->PostTask(
420       FROM_HERE,
421       base::Bind(&SyncWorker::QueryAppStatusOnUIThread,
422                  extension_service_,
423                  base::Owned(app_ids.release()),
424                  app_status,
425                  RelayCallbackToTaskRunner(
426                      context_->GetWorkerTaskRunner(),
427                      FROM_HERE, callback)));
428 }
429
430 void SyncWorker::QueryAppStatusOnUIThread(
431     const base::WeakPtr<ExtensionServiceInterface>& extension_service_ptr,
432     const std::vector<std::string>* app_ids,
433     AppStatusMap* status,
434     const base::Closure& callback) {
435   ExtensionServiceInterface* extension_service = extension_service_ptr.get();
436   if (!extension_service) {
437     callback.Run();
438     return;
439   }
440
441   for (std::vector<std::string>::const_iterator itr = app_ids->begin();
442        itr != app_ids->end(); ++itr) {
443     const std::string& app_id = *itr;
444     if (!extension_service->GetInstalledExtension(app_id))
445       (*status)[app_id] = APP_STATUS_UNINSTALLED;
446     else if (!extension_service->IsExtensionEnabled(app_id))
447       (*status)[app_id] = APP_STATUS_DISABLED;
448     else
449       (*status)[app_id] = APP_STATUS_ENABLED;
450   }
451
452   callback.Run();
453 }
454
455 void SyncWorker::DidQueryAppStatus(const AppStatusMap* app_status) {
456   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
457
458   MetadataDatabase* metadata_db = GetMetadataDatabase();
459   DCHECK(metadata_db);
460
461   // Update the status of every origin using status from ExtensionService.
462   for (AppStatusMap::const_iterator itr = app_status->begin();
463        itr != app_status->end(); ++itr) {
464     const std::string& app_id = itr->first;
465     GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
466
467     if (itr->second == APP_STATUS_UNINSTALLED) {
468       // Extension has been uninstalled.
469       // (At this stage we can't know if it was unpacked extension or not,
470       // so just purge the remote folder.)
471       UninstallOrigin(origin,
472                       RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
473                       base::Bind(&EmptyStatusCallback));
474       continue;
475     }
476
477     FileTracker tracker;
478     if (!metadata_db->FindAppRootTracker(app_id, &tracker)) {
479       // App will register itself on first run.
480       continue;
481     }
482
483     DCHECK(itr->second == APP_STATUS_ENABLED ||
484            itr->second == APP_STATUS_DISABLED);
485     bool is_app_enabled = (itr->second == APP_STATUS_ENABLED);
486     bool is_app_root_tracker_enabled =
487         (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT);
488     if (is_app_enabled && !is_app_root_tracker_enabled)
489       EnableOrigin(origin, base::Bind(&EmptyStatusCallback));
490     else if (!is_app_enabled && is_app_root_tracker_enabled)
491       DisableOrigin(origin, base::Bind(&EmptyStatusCallback));
492   }
493 }
494
495 void SyncWorker::DidProcessRemoteChange(RemoteToLocalSyncer* syncer,
496                                         const SyncFileCallback& callback,
497                                         SyncStatusCode status) {
498   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
499
500   if (syncer->is_sync_root_deletion()) {
501     MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase());
502     PostInitializeTask();
503     callback.Run(status, syncer->url());
504     return;
505   }
506
507   if (status == SYNC_STATUS_OK) {
508     if (syncer->sync_action() != SYNC_ACTION_NONE &&
509         syncer->url().is_valid()) {
510       FOR_EACH_OBSERVER(
511           Observer, observers_,
512           OnFileStatusChanged(
513               syncer->url(),
514               syncer->file_type(),
515               SYNC_FILE_STATUS_SYNCED,
516               syncer->sync_action(),
517               SYNC_DIRECTION_REMOTE_TO_LOCAL));
518     }
519
520     if (syncer->sync_action() == SYNC_ACTION_DELETED &&
521         syncer->url().is_valid() &&
522         storage::VirtualPath::IsRootPath(syncer->url().path())) {
523       RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback));
524     }
525     should_check_conflict_ = true;
526   }
527   callback.Run(status, syncer->url());
528 }
529
530 void SyncWorker::DidApplyLocalChange(LocalToRemoteSyncer* syncer,
531                                      const SyncStatusCallback& callback,
532                                      SyncStatusCode status) {
533   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
534
535   if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) &&
536       syncer->url().is_valid() &&
537       syncer->sync_action() != SYNC_ACTION_NONE) {
538     storage::FileSystemURL updated_url = syncer->url();
539     if (!syncer->target_path().empty()) {
540       updated_url = CreateSyncableFileSystemURL(syncer->url().origin(),
541                                                 syncer->target_path());
542     }
543     FOR_EACH_OBSERVER(Observer, observers_,
544                       OnFileStatusChanged(updated_url,
545                                           syncer->file_type(),
546                                           SYNC_FILE_STATUS_SYNCED,
547                                           syncer->sync_action(),
548                                           SYNC_DIRECTION_LOCAL_TO_REMOTE));
549   }
550
551   if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) {
552     RegisterOrigin(syncer->url().origin(),
553                    base::Bind(&EmptyStatusCallback));
554   }
555
556   if (syncer->needs_remote_change_listing() &&
557       !listing_remote_changes_) {
558     task_manager_->ScheduleSyncTask(
559         FROM_HERE,
560         scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
561         SyncTaskManager::PRIORITY_HIGH,
562         base::Bind(&SyncWorker::DidFetchChanges,
563                    weak_ptr_factory_.GetWeakPtr()));
564     should_check_remote_change_ = false;
565     listing_remote_changes_ = true;
566     time_to_check_changes_ =
567         base::TimeTicks::Now() +
568         base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
569   }
570
571   if (status == SYNC_STATUS_OK)
572     should_check_conflict_ = true;
573
574   callback.Run(status);
575 }
576
577 bool SyncWorker::MaybeStartFetchChanges() {
578   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
579
580   if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
581     return false;
582
583   if (!GetMetadataDatabase())
584     return false;
585
586   if (listing_remote_changes_)
587     return false;
588
589   base::TimeTicks now = base::TimeTicks::Now();
590   if (!should_check_remote_change_ && now < time_to_check_changes_) {
591     if (!GetMetadataDatabase()->HasDirtyTracker() &&
592         should_check_conflict_) {
593       should_check_conflict_ = false;
594       return task_manager_->ScheduleSyncTaskIfIdle(
595           FROM_HERE,
596           scoped_ptr<SyncTask>(new ConflictResolver(context_.get())),
597           base::Bind(&SyncWorker::DidResolveConflict,
598                      weak_ptr_factory_.GetWeakPtr()));
599     }
600     return false;
601   }
602
603   if (task_manager_->ScheduleSyncTaskIfIdle(
604           FROM_HERE,
605           scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
606           base::Bind(&SyncWorker::DidFetchChanges,
607                      weak_ptr_factory_.GetWeakPtr()))) {
608     should_check_remote_change_ = false;
609     listing_remote_changes_ = true;
610     time_to_check_changes_ =
611         now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
612     return true;
613   }
614   return false;
615 }
616
617 void SyncWorker::DidResolveConflict(SyncStatusCode status) {
618   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
619
620   if (status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY)
621     should_check_conflict_ = true;
622 }
623
624 void SyncWorker::DidFetchChanges(SyncStatusCode status) {
625   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
626
627   if (status == SYNC_STATUS_OK)
628     should_check_conflict_ = true;
629   listing_remote_changes_ = false;
630 }
631
632 void SyncWorker::UpdateServiceStateFromSyncStatusCode(
633     SyncStatusCode status,
634     bool used_network) {
635   switch (status) {
636     case SYNC_STATUS_OK:
637       if (used_network)
638         UpdateServiceState(REMOTE_SERVICE_OK, std::string());
639       break;
640
641     // Authentication error.
642     case SYNC_STATUS_AUTHENTICATION_FAILED:
643       UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
644                          "Authentication required");
645       break;
646
647     // OAuth token error.
648     case SYNC_STATUS_ACCESS_FORBIDDEN:
649       UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN,
650                          "Access forbidden");
651       break;
652
653     // Errors which could make the service temporarily unavailable.
654     case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE:
655     case SYNC_STATUS_NETWORK_ERROR:
656     case SYNC_STATUS_ABORT:
657     case SYNC_STATUS_FAILED:
658       UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
659                          "Network or temporary service error.");
660       break;
661
662     // Errors which would require manual user intervention to resolve.
663     case SYNC_DATABASE_ERROR_CORRUPTION:
664     case SYNC_DATABASE_ERROR_IO_ERROR:
665     case SYNC_DATABASE_ERROR_FAILED:
666       UpdateServiceState(REMOTE_SERVICE_DISABLED,
667                          "Unrecoverable database error");
668       break;
669
670     default:
671       // Other errors don't affect service state
672       break;
673   }
674 }
675
676 void SyncWorker::UpdateServiceState(RemoteServiceState state,
677                                     const std::string& description) {
678   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
679
680   RemoteServiceState old_state = GetCurrentState();
681   service_state_ = state;
682
683   if (old_state == GetCurrentState())
684     return;
685
686   util::Log(logging::LOG_VERBOSE, FROM_HERE,
687             "Service state changed: %d->%d: %s",
688             old_state, GetCurrentState(), description.c_str());
689
690   FOR_EACH_OBSERVER(
691       Observer, observers_,
692       UpdateServiceState(GetCurrentState(), description));
693 }
694
695 void SyncWorker::CallOnIdleForTesting(const base::Closure& callback) {
696   if (task_manager_->ScheduleTaskIfIdle(
697           FROM_HERE,
698           base::Bind(&InvokeIdleCallback, callback),
699           base::Bind(&EmptyStatusCallback)))
700     return;
701   call_on_idle_callback_ = base::Bind(
702       &SyncWorker::CallOnIdleForTesting,
703       weak_ptr_factory_.GetWeakPtr(),
704       callback);
705 }
706
707 drive::DriveServiceInterface* SyncWorker::GetDriveService() {
708   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
709   return context_->GetDriveService();
710 }
711
712 drive::DriveUploaderInterface* SyncWorker::GetDriveUploader() {
713   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
714   return context_->GetDriveUploader();
715 }
716
717 MetadataDatabase* SyncWorker::GetMetadataDatabase() {
718   DCHECK(sequence_checker_.CalledOnValidSequencedThread());
719   return context_->GetMetadataDatabase();
720 }
721
722 }  // namespace drive_backend
723 }  // namespace sync_file_system