Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / drive_backend / sync_worker.cc
blob1cb1c4e08cfc181e3cc040ca1493f7db88432fc8
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.
5 #include "chrome/browser/sync_file_system/drive_backend/sync_worker.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h"
12 #include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
13 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
14 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
15 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h"
16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
17 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
18 #include "chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.h"
19 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
20 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
22 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
23 #include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h"
24 #include "chrome/browser/sync_file_system/logger.h"
25 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
26 #include "components/drive/service/drive_service_interface.h"
27 #include "storage/common/fileapi/file_system_util.h"
29 namespace sync_file_system {
31 class RemoteChangeProcessor;
33 namespace drive_backend {
35 namespace {
37 void EmptyStatusCallback(SyncStatusCode status) {}
39 void InvokeIdleCallback(const base::Closure& idle_callback,
40 const SyncStatusCallback& callback) {
41 idle_callback.Run();
42 callback.Run(SYNC_STATUS_OK);
45 } // namespace
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());
64 SyncWorker::~SyncWorker() {
65 observers_.Clear();
68 void SyncWorker::Initialize(scoped_ptr<SyncEngineContext> context) {
69 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
70 DCHECK(!task_manager_);
72 context_ = context.Pass();
74 task_manager_.reset(new SyncTaskManager(
75 weak_ptr_factory_.GetWeakPtr(), 0 /* maximum_background_task */,
76 context_->GetWorkerTaskRunner(),
77 context_->GetWorkerPool()));
78 task_manager_->Initialize(SYNC_STATUS_OK);
80 PostInitializeTask();
83 void SyncWorker::RegisterOrigin(
84 const GURL& origin,
85 const SyncStatusCallback& callback) {
86 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
88 if (!GetMetadataDatabase())
89 PostInitializeTask();
91 scoped_ptr<RegisterAppTask> task(
92 new RegisterAppTask(context_.get(), origin.host()));
93 if (task->CanFinishImmediately()) {
94 callback.Run(SYNC_STATUS_OK);
95 return;
98 task_manager_->ScheduleSyncTask(
99 FROM_HERE, task.Pass(), SyncTaskManager::PRIORITY_HIGH, callback);
102 void SyncWorker::EnableOrigin(
103 const GURL& origin,
104 const SyncStatusCallback& callback) {
105 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
107 task_manager_->ScheduleTask(
108 FROM_HERE,
109 base::Bind(&SyncWorker::DoEnableApp,
110 weak_ptr_factory_.GetWeakPtr(),
111 origin.host()),
112 SyncTaskManager::PRIORITY_HIGH,
113 callback);
116 void SyncWorker::DisableOrigin(
117 const GURL& origin,
118 const SyncStatusCallback& callback) {
119 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
121 task_manager_->ScheduleTask(
122 FROM_HERE,
123 base::Bind(&SyncWorker::DoDisableApp,
124 weak_ptr_factory_.GetWeakPtr(),
125 origin.host()),
126 SyncTaskManager::PRIORITY_HIGH,
127 callback);
130 void SyncWorker::UninstallOrigin(
131 const GURL& origin,
132 RemoteFileSyncService::UninstallFlag flag,
133 const SyncStatusCallback& callback) {
134 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
136 task_manager_->ScheduleSyncTask(
137 FROM_HERE,
138 scoped_ptr<SyncTask>(
139 new UninstallAppTask(context_.get(), origin.host(), flag)),
140 SyncTaskManager::PRIORITY_HIGH,
141 callback);
144 void SyncWorker::ProcessRemoteChange(const SyncFileCallback& callback) {
145 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
147 RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(context_.get());
148 task_manager_->ScheduleSyncTask(
149 FROM_HERE,
150 scoped_ptr<SyncTask>(syncer),
151 SyncTaskManager::PRIORITY_MED,
152 base::Bind(&SyncWorker::DidProcessRemoteChange,
153 weak_ptr_factory_.GetWeakPtr(),
154 syncer,
155 callback));
158 void SyncWorker::SetRemoteChangeProcessor(
159 RemoteChangeProcessorOnWorker* remote_change_processor_on_worker) {
160 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
162 context_->SetRemoteChangeProcessor(remote_change_processor_on_worker);
165 RemoteServiceState SyncWorker::GetCurrentState() const {
166 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
168 if (!sync_enabled_)
169 return REMOTE_SERVICE_DISABLED;
170 return service_state_;
173 void SyncWorker::GetOriginStatusMap(
174 const RemoteFileSyncService::StatusMapCallback& callback) {
175 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
177 if (!GetMetadataDatabase())
178 return;
180 std::vector<std::string> app_ids;
181 GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
183 scoped_ptr<RemoteFileSyncService::OriginStatusMap>
184 status_map(new RemoteFileSyncService::OriginStatusMap);
185 for (std::vector<std::string>::const_iterator itr = app_ids.begin();
186 itr != app_ids.end(); ++itr) {
187 const std::string& app_id = *itr;
188 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
189 (*status_map)[origin] =
190 GetMetadataDatabase()->IsAppEnabled(app_id) ? "Enabled" : "Disabled";
193 callback.Run(status_map.Pass());
196 scoped_ptr<base::ListValue> SyncWorker::DumpFiles(const GURL& origin) {
197 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
199 if (!GetMetadataDatabase())
200 return scoped_ptr<base::ListValue>();
201 return GetMetadataDatabase()->DumpFiles(origin.host());
204 scoped_ptr<base::ListValue> SyncWorker::DumpDatabase() {
205 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
207 if (!GetMetadataDatabase())
208 return scoped_ptr<base::ListValue>();
209 return GetMetadataDatabase()->DumpDatabase();
212 void SyncWorker::SetSyncEnabled(bool enabled) {
213 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
215 if (sync_enabled_ == enabled)
216 return;
218 RemoteServiceState old_state = GetCurrentState();
219 sync_enabled_ = enabled;
220 if (old_state == GetCurrentState())
221 return;
223 FOR_EACH_OBSERVER(
224 Observer,
225 observers_,
226 UpdateServiceState(
227 GetCurrentState(),
228 enabled ? "Sync is enabled" : "Sync is disabled"));
231 void SyncWorker::PromoteDemotedChanges(const base::Closure& callback) {
232 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
234 MetadataDatabase* metadata_db = GetMetadataDatabase();
235 if (metadata_db && metadata_db->HasDemotedDirtyTracker()) {
236 metadata_db->PromoteDemotedTrackers();
237 FOR_EACH_OBSERVER(
238 Observer,
239 observers_,
240 OnPendingFileListUpdated(metadata_db->CountDirtyTracker()));
242 callback.Run();
245 void SyncWorker::ApplyLocalChange(const FileChange& local_change,
246 const base::FilePath& local_path,
247 const SyncFileMetadata& local_metadata,
248 const storage::FileSystemURL& url,
249 const SyncStatusCallback& callback) {
250 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
252 LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer(
253 context_.get(), local_metadata, local_change, local_path, url);
254 task_manager_->ScheduleSyncTask(
255 FROM_HERE,
256 scoped_ptr<SyncTask>(syncer),
257 SyncTaskManager::PRIORITY_MED,
258 base::Bind(&SyncWorker::DidApplyLocalChange,
259 weak_ptr_factory_.GetWeakPtr(),
260 syncer,
261 callback));
264 void SyncWorker::MaybeScheduleNextTask() {
265 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
267 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
268 return;
270 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated.
271 // TODO(tzik): Add an interface to get the number of dirty trackers to
272 // MetadataDatabase.
274 if (MaybeStartFetchChanges())
275 return;
277 if (!call_on_idle_callback_.is_null()) {
278 base::Closure callback = call_on_idle_callback_;
279 call_on_idle_callback_.Reset();
280 callback.Run();
284 void SyncWorker::NotifyLastOperationStatus(
285 SyncStatusCode status,
286 bool used_network) {
287 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
289 UpdateServiceStateFromSyncStatusCode(status, used_network);
291 if (GetMetadataDatabase()) {
292 FOR_EACH_OBSERVER(
293 Observer, observers_,
294 OnPendingFileListUpdated(GetMetadataDatabase()->CountDirtyTracker()));
298 void SyncWorker::RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) {
299 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
301 context_->GetUITaskRunner()->PostTask(
302 FROM_HERE,
303 base::Bind(&TaskLogger::RecordLog,
304 context_->GetTaskLogger(),
305 base::Passed(&task_log)));
308 void SyncWorker::ActivateService(RemoteServiceState service_state,
309 const std::string& description) {
310 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
311 UpdateServiceState(service_state, description);
312 if (!GetMetadataDatabase()) {
313 PostInitializeTask();
314 return;
317 should_check_remote_change_ = true;
318 MaybeScheduleNextTask();
321 void SyncWorker::DeactivateService(const std::string& description) {
322 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
323 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, description);
326 void SyncWorker::DetachFromSequence() {
327 task_manager_->DetachFromSequence();
328 context_->DetachFromSequence();
329 sequence_checker_.DetachFromSequence();
332 void SyncWorker::AddObserver(Observer* observer) {
333 observers_.AddObserver(observer);
336 void SyncWorker::DoDisableApp(const std::string& app_id,
337 const SyncStatusCallback& callback) {
338 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
340 if (!GetMetadataDatabase()) {
341 callback.Run(SYNC_STATUS_OK);
342 return;
345 SyncStatusCode status = GetMetadataDatabase()->DisableApp(app_id);
346 callback.Run(status);
349 void SyncWorker::DoEnableApp(const std::string& app_id,
350 const SyncStatusCallback& callback) {
351 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
353 if (!GetMetadataDatabase()) {
354 callback.Run(SYNC_STATUS_OK);
355 return;
358 SyncStatusCode status = GetMetadataDatabase()->EnableApp(app_id);
359 callback.Run(status);
362 void SyncWorker::PostInitializeTask() {
363 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
364 DCHECK(!GetMetadataDatabase());
366 // This initializer task may not run if MetadataDatabase in context_ is
367 // already initialized when it runs.
368 SyncEngineInitializer* initializer =
369 new SyncEngineInitializer(context_.get(),
370 base_dir_.Append(kDatabaseName),
371 env_override_);
372 task_manager_->ScheduleSyncTask(
373 FROM_HERE,
374 scoped_ptr<SyncTask>(initializer),
375 SyncTaskManager::PRIORITY_HIGH,
376 base::Bind(&SyncWorker::DidInitialize,
377 weak_ptr_factory_.GetWeakPtr(),
378 initializer));
381 void SyncWorker::DidInitialize(SyncEngineInitializer* initializer,
382 SyncStatusCode status) {
383 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
385 if (status == SYNC_STATUS_ACCESS_FORBIDDEN) {
386 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN, "Access forbidden");
387 return;
389 if (status != SYNC_STATUS_OK) {
390 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
391 "Could not initialize remote service");
392 return;
395 scoped_ptr<MetadataDatabase> metadata_database =
396 initializer->PassMetadataDatabase();
397 if (metadata_database) {
398 context_->SetMetadataDatabase(metadata_database.Pass());
399 return;
402 UpdateServiceState(REMOTE_SERVICE_OK, std::string());
403 UpdateRegisteredApps();
406 void SyncWorker::UpdateRegisteredApps() {
407 MetadataDatabase* metadata_db = GetMetadataDatabase();
408 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
409 DCHECK(metadata_db);
411 scoped_ptr<std::vector<std::string> > app_ids(new std::vector<std::string>);
412 metadata_db->GetRegisteredAppIDs(app_ids.get());
414 AppStatusMap* app_status = new AppStatusMap;
415 base::Closure callback =
416 base::Bind(&SyncWorker::DidQueryAppStatus,
417 weak_ptr_factory_.GetWeakPtr(),
418 base::Owned(app_status));
420 context_->GetUITaskRunner()->PostTask(
421 FROM_HERE,
422 base::Bind(&SyncWorker::QueryAppStatusOnUIThread,
423 extension_service_,
424 base::Owned(app_ids.release()),
425 app_status,
426 RelayCallbackToTaskRunner(
427 context_->GetWorkerTaskRunner(),
428 FROM_HERE, callback)));
431 void SyncWorker::QueryAppStatusOnUIThread(
432 const base::WeakPtr<ExtensionServiceInterface>& extension_service_ptr,
433 const std::vector<std::string>* app_ids,
434 AppStatusMap* status,
435 const base::Closure& callback) {
436 ExtensionServiceInterface* extension_service = extension_service_ptr.get();
437 if (!extension_service) {
438 callback.Run();
439 return;
442 for (std::vector<std::string>::const_iterator itr = app_ids->begin();
443 itr != app_ids->end(); ++itr) {
444 const std::string& app_id = *itr;
445 if (!extension_service->GetInstalledExtension(app_id))
446 (*status)[app_id] = APP_STATUS_UNINSTALLED;
447 else if (!extension_service->IsExtensionEnabled(app_id))
448 (*status)[app_id] = APP_STATUS_DISABLED;
449 else
450 (*status)[app_id] = APP_STATUS_ENABLED;
453 callback.Run();
456 void SyncWorker::DidQueryAppStatus(const AppStatusMap* app_status) {
457 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
459 MetadataDatabase* metadata_db = GetMetadataDatabase();
460 DCHECK(metadata_db);
462 // Update the status of every origin using status from ExtensionService.
463 for (AppStatusMap::const_iterator itr = app_status->begin();
464 itr != app_status->end(); ++itr) {
465 const std::string& app_id = itr->first;
466 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
468 if (itr->second == APP_STATUS_UNINSTALLED) {
469 // Extension has been uninstalled.
470 // (At this stage we can't know if it was unpacked extension or not,
471 // so just purge the remote folder.)
472 UninstallOrigin(origin,
473 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
474 base::Bind(&EmptyStatusCallback));
475 continue;
478 FileTracker tracker;
479 if (!metadata_db->FindAppRootTracker(app_id, &tracker)) {
480 // App will register itself on first run.
481 continue;
484 DCHECK(itr->second == APP_STATUS_ENABLED ||
485 itr->second == APP_STATUS_DISABLED);
486 bool is_app_enabled = (itr->second == APP_STATUS_ENABLED);
487 bool is_app_root_tracker_enabled =
488 (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT);
489 if (is_app_enabled && !is_app_root_tracker_enabled)
490 EnableOrigin(origin, base::Bind(&EmptyStatusCallback));
491 else if (!is_app_enabled && is_app_root_tracker_enabled)
492 DisableOrigin(origin, base::Bind(&EmptyStatusCallback));
496 void SyncWorker::DidProcessRemoteChange(RemoteToLocalSyncer* syncer,
497 const SyncFileCallback& callback,
498 SyncStatusCode status) {
499 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
501 if (syncer->is_sync_root_deletion()) {
502 MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase());
503 PostInitializeTask();
504 callback.Run(status, syncer->url());
505 return;
508 if (status == SYNC_STATUS_OK) {
509 if (syncer->sync_action() != SYNC_ACTION_NONE &&
510 syncer->url().is_valid()) {
511 FOR_EACH_OBSERVER(
512 Observer, observers_,
513 OnFileStatusChanged(
514 syncer->url(),
515 syncer->file_type(),
516 SYNC_FILE_STATUS_SYNCED,
517 syncer->sync_action(),
518 SYNC_DIRECTION_REMOTE_TO_LOCAL));
521 if (syncer->sync_action() == SYNC_ACTION_DELETED &&
522 syncer->url().is_valid() &&
523 storage::VirtualPath::IsRootPath(syncer->url().path())) {
524 RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback));
526 should_check_conflict_ = true;
528 callback.Run(status, syncer->url());
531 void SyncWorker::DidApplyLocalChange(LocalToRemoteSyncer* syncer,
532 const SyncStatusCallback& callback,
533 SyncStatusCode status) {
534 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
536 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) &&
537 syncer->url().is_valid() &&
538 syncer->sync_action() != SYNC_ACTION_NONE) {
539 storage::FileSystemURL updated_url = syncer->url();
540 if (!syncer->target_path().empty()) {
541 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(),
542 syncer->target_path());
544 FOR_EACH_OBSERVER(Observer, observers_,
545 OnFileStatusChanged(updated_url,
546 syncer->file_type(),
547 SYNC_FILE_STATUS_SYNCED,
548 syncer->sync_action(),
549 SYNC_DIRECTION_LOCAL_TO_REMOTE));
552 if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) {
553 RegisterOrigin(syncer->url().origin(),
554 base::Bind(&EmptyStatusCallback));
557 if (syncer->needs_remote_change_listing() &&
558 !listing_remote_changes_) {
559 task_manager_->ScheduleSyncTask(
560 FROM_HERE,
561 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
562 SyncTaskManager::PRIORITY_HIGH,
563 base::Bind(&SyncWorker::DidFetchChanges,
564 weak_ptr_factory_.GetWeakPtr()));
565 should_check_remote_change_ = false;
566 listing_remote_changes_ = true;
567 time_to_check_changes_ =
568 base::TimeTicks::Now() +
569 base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
572 if (status == SYNC_STATUS_OK)
573 should_check_conflict_ = true;
575 callback.Run(status);
578 bool SyncWorker::MaybeStartFetchChanges() {
579 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
581 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
582 return false;
584 if (!GetMetadataDatabase())
585 return false;
587 if (listing_remote_changes_)
588 return false;
590 base::TimeTicks now = base::TimeTicks::Now();
591 if (!should_check_remote_change_ && now < time_to_check_changes_) {
592 if (!GetMetadataDatabase()->HasDirtyTracker() &&
593 should_check_conflict_) {
594 should_check_conflict_ = false;
595 return task_manager_->ScheduleSyncTaskIfIdle(
596 FROM_HERE,
597 scoped_ptr<SyncTask>(new ConflictResolver(context_.get())),
598 base::Bind(&SyncWorker::DidResolveConflict,
599 weak_ptr_factory_.GetWeakPtr()));
601 return false;
604 if (task_manager_->ScheduleSyncTaskIfIdle(
605 FROM_HERE,
606 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
607 base::Bind(&SyncWorker::DidFetchChanges,
608 weak_ptr_factory_.GetWeakPtr()))) {
609 should_check_remote_change_ = false;
610 listing_remote_changes_ = true;
611 time_to_check_changes_ =
612 now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
613 return true;
615 return false;
618 void SyncWorker::DidResolveConflict(SyncStatusCode status) {
619 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
621 if (status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY)
622 should_check_conflict_ = true;
625 void SyncWorker::DidFetchChanges(SyncStatusCode status) {
626 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
628 if (status == SYNC_STATUS_OK)
629 should_check_conflict_ = true;
630 listing_remote_changes_ = false;
633 void SyncWorker::UpdateServiceStateFromSyncStatusCode(
634 SyncStatusCode status,
635 bool used_network) {
636 switch (status) {
637 case SYNC_STATUS_OK:
638 if (used_network)
639 UpdateServiceState(REMOTE_SERVICE_OK, std::string());
640 break;
642 // Authentication error.
643 case SYNC_STATUS_AUTHENTICATION_FAILED:
644 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
645 "Authentication required");
646 break;
648 // OAuth token error.
649 case SYNC_STATUS_ACCESS_FORBIDDEN:
650 UpdateServiceState(REMOTE_SERVICE_ACCESS_FORBIDDEN,
651 "Access forbidden");
652 break;
654 // Errors which could make the service temporarily unavailable.
655 case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE:
656 case SYNC_STATUS_NETWORK_ERROR:
657 case SYNC_STATUS_ABORT:
658 case SYNC_STATUS_FAILED:
659 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
660 "Network or temporary service error.");
661 break;
663 // Errors which would require manual user intervention to resolve.
664 case SYNC_DATABASE_ERROR_CORRUPTION:
665 case SYNC_DATABASE_ERROR_IO_ERROR:
666 case SYNC_DATABASE_ERROR_FAILED:
667 UpdateServiceState(REMOTE_SERVICE_DISABLED,
668 "Unrecoverable database error");
669 break;
671 default:
672 // Other errors don't affect service state
673 break;
677 void SyncWorker::UpdateServiceState(RemoteServiceState state,
678 const std::string& description) {
679 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
681 RemoteServiceState old_state = GetCurrentState();
682 service_state_ = state;
684 if (old_state == GetCurrentState())
685 return;
687 util::Log(logging::LOG_VERBOSE, FROM_HERE,
688 "Service state changed: %d->%d: %s",
689 old_state, GetCurrentState(), description.c_str());
691 FOR_EACH_OBSERVER(
692 Observer, observers_,
693 UpdateServiceState(GetCurrentState(), description));
696 void SyncWorker::CallOnIdleForTesting(const base::Closure& callback) {
697 if (task_manager_->ScheduleTaskIfIdle(
698 FROM_HERE,
699 base::Bind(&InvokeIdleCallback, callback),
700 base::Bind(&EmptyStatusCallback)))
701 return;
702 call_on_idle_callback_ = base::Bind(
703 &SyncWorker::CallOnIdleForTesting,
704 weak_ptr_factory_.GetWeakPtr(),
705 callback);
708 drive::DriveServiceInterface* SyncWorker::GetDriveService() {
709 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
710 return context_->GetDriveService();
713 drive::DriveUploaderInterface* SyncWorker::GetDriveUploader() {
714 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
715 return context_->GetDriveUploader();
718 MetadataDatabase* SyncWorker::GetMetadataDatabase() {
719 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
720 return context_->GetMetadataDatabase();
723 } // namespace drive_backend
724 } // namespace sync_file_system