Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / drive_backend / sync_engine.cc
blob1723a9166669b04d8df786f67edbe144777a5970
1 // Copyright 2013 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_engine.h"
7 #include "base/bind.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "base/values.h"
10 #include "chrome/browser/drive/drive_api_service.h"
11 #include "chrome/browser/drive/drive_notification_manager.h"
12 #include "chrome/browser/drive/drive_notification_manager_factory.h"
13 #include "chrome/browser/drive/drive_service_interface.h"
14 #include "chrome/browser/drive/drive_uploader.h"
15 #include "chrome/browser/drive/drive_uploader.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_system_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/signin/profile_oauth2_token_service.h"
21 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
22 #include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
23 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
24 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
25 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h"
26 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
27 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
28 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
29 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
30 #include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h"
31 #include "chrome/browser/sync_file_system/file_status_observer.h"
32 #include "chrome/browser/sync_file_system/logger.h"
33 #include "chrome/browser/sync_file_system/sync_task.h"
34 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "extensions/common/extension.h"
37 #include "google_apis/drive/drive_api_url_generator.h"
38 #include "google_apis/drive/gdata_wapi_url_generator.h"
39 #include "webkit/common/blob/scoped_file.h"
40 #include "webkit/common/fileapi/file_system_util.h"
42 namespace sync_file_system {
43 namespace drive_backend {
45 namespace {
47 void EmptyStatusCallback(SyncStatusCode status) {}
49 } // namespace
51 scoped_ptr<SyncEngine> SyncEngine::CreateForBrowserContext(
52 content::BrowserContext* context) {
53 GURL base_drive_url(
54 google_apis::DriveApiUrlGenerator::kBaseUrlForProduction);
55 GURL base_download_url(
56 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction);
57 GURL wapi_base_url(
58 google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction);
60 scoped_refptr<base::SequencedWorkerPool> worker_pool(
61 content::BrowserThread::GetBlockingPool());
62 scoped_refptr<base::SequencedTaskRunner> drive_task_runner(
63 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
64 worker_pool->GetSequenceToken(),
65 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
67 ProfileOAuth2TokenService* token_service =
68 ProfileOAuth2TokenServiceFactory::GetForProfile(
69 Profile::FromBrowserContext(context));
70 scoped_ptr<drive::DriveServiceInterface> drive_service(
71 new drive::DriveAPIService(
72 token_service,
73 context->GetRequestContext(),
74 drive_task_runner.get(),
75 base_drive_url, base_download_url, wapi_base_url,
76 std::string() /* custom_user_agent */));
77 drive_service->Initialize(token_service->GetPrimaryAccountId());
79 scoped_ptr<drive::DriveUploaderInterface> drive_uploader(
80 new drive::DriveUploader(drive_service.get(), drive_task_runner.get()));
82 drive::DriveNotificationManager* notification_manager =
83 drive::DriveNotificationManagerFactory::GetForBrowserContext(context);
84 ExtensionService* extension_service =
85 extensions::ExtensionSystem::GetForBrowserContext(
86 context)->extension_service();
88 scoped_refptr<base::SequencedTaskRunner> task_runner(
89 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
90 worker_pool->GetSequenceToken(),
91 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
93 scoped_ptr<drive_backend::SyncEngine> sync_engine(
94 new SyncEngine(
95 GetSyncFileSystemDir(context->GetPath()),
96 task_runner.get(),
97 drive_service.Pass(),
98 drive_uploader.Pass(),
99 notification_manager,
100 extension_service,
101 token_service));
102 sync_engine->Initialize();
104 return sync_engine.Pass();
107 void SyncEngine::AppendDependsOnFactories(
108 std::set<BrowserContextKeyedServiceFactory*>* factories) {
109 DCHECK(factories);
110 factories->insert(drive::DriveNotificationManagerFactory::GetInstance());
111 factories->insert(ProfileOAuth2TokenServiceFactory::GetInstance());
112 factories->insert(extensions::ExtensionSystemFactory::GetInstance());
115 SyncEngine::~SyncEngine() {
116 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
117 drive_service_->RemoveObserver(this);
118 if (notification_manager_)
119 notification_manager_->RemoveObserver(this);
122 void SyncEngine::Initialize() {
123 DCHECK(!task_manager_);
124 task_manager_.reset(new SyncTaskManager(weak_ptr_factory_.GetWeakPtr()));
125 task_manager_->Initialize(SYNC_STATUS_OK);
127 PostInitializeTask();
129 if (notification_manager_)
130 notification_manager_->AddObserver(this);
131 drive_service_->AddObserver(this);
132 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
134 net::NetworkChangeNotifier::ConnectionType type =
135 net::NetworkChangeNotifier::GetConnectionType();
136 network_available_ =
137 type != net::NetworkChangeNotifier::CONNECTION_NONE;
140 void SyncEngine::AddServiceObserver(SyncServiceObserver* observer) {
141 service_observers_.AddObserver(observer);
144 void SyncEngine::AddFileStatusObserver(FileStatusObserver* observer) {
145 file_status_observers_.AddObserver(observer);
148 void SyncEngine::RegisterOrigin(
149 const GURL& origin,
150 const SyncStatusCallback& callback) {
151 if (!metadata_database_ && drive_service_->HasRefreshToken())
152 PostInitializeTask();
154 task_manager_->ScheduleSyncTaskAtPriority(
155 scoped_ptr<SyncTask>(new RegisterAppTask(this, origin.host())),
156 SyncTaskManager::PRIORITY_HIGH,
157 callback);
160 void SyncEngine::EnableOrigin(
161 const GURL& origin,
162 const SyncStatusCallback& callback) {
163 task_manager_->ScheduleTaskAtPriority(
164 base::Bind(&SyncEngine::DoEnableApp,
165 weak_ptr_factory_.GetWeakPtr(),
166 origin.host()),
167 SyncTaskManager::PRIORITY_HIGH,
168 callback);
171 void SyncEngine::DisableOrigin(
172 const GURL& origin,
173 const SyncStatusCallback& callback) {
174 task_manager_->ScheduleTaskAtPriority(
175 base::Bind(&SyncEngine::DoDisableApp,
176 weak_ptr_factory_.GetWeakPtr(),
177 origin.host()),
178 SyncTaskManager::PRIORITY_HIGH,
179 callback);
182 void SyncEngine::UninstallOrigin(
183 const GURL& origin,
184 UninstallFlag flag,
185 const SyncStatusCallback& callback) {
186 task_manager_->ScheduleSyncTaskAtPriority(
187 scoped_ptr<SyncTask>(new UninstallAppTask(this, origin.host(), flag)),
188 SyncTaskManager::PRIORITY_HIGH,
189 callback);
192 void SyncEngine::ProcessRemoteChange(
193 const SyncFileCallback& callback) {
194 RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(this);
195 task_manager_->ScheduleSyncTask(
196 scoped_ptr<SyncTask>(syncer),
197 base::Bind(&SyncEngine::DidProcessRemoteChange,
198 weak_ptr_factory_.GetWeakPtr(),
199 syncer, callback));
202 void SyncEngine::SetRemoteChangeProcessor(
203 RemoteChangeProcessor* processor) {
204 remote_change_processor_ = processor;
207 LocalChangeProcessor* SyncEngine::GetLocalChangeProcessor() {
208 return this;
211 bool SyncEngine::IsConflicting(const fileapi::FileSystemURL& url) {
212 // TODO(tzik): Implement this before we support manual conflict resolution.
213 return false;
216 RemoteServiceState SyncEngine::GetCurrentState() const {
217 return service_state_;
220 void SyncEngine::GetOriginStatusMap(OriginStatusMap* status_map) {
221 DCHECK(status_map);
222 if (!extension_service_ || !metadata_database_)
223 return;
225 std::vector<std::string> app_ids;
226 metadata_database_->GetRegisteredAppIDs(&app_ids);
228 for (std::vector<std::string>::const_iterator itr = app_ids.begin();
229 itr != app_ids.end(); ++itr) {
230 const std::string& app_id = *itr;
231 GURL origin =
232 extensions::Extension::GetBaseURLFromExtensionId(app_id);
233 (*status_map)[origin] =
234 metadata_database_->IsAppEnabled(app_id) ? "Enabled" : "Disabled";
238 scoped_ptr<base::ListValue> SyncEngine::DumpFiles(const GURL& origin) {
239 if (!metadata_database_)
240 return scoped_ptr<base::ListValue>();
241 return metadata_database_->DumpFiles(origin.host());
244 scoped_ptr<base::ListValue> SyncEngine::DumpDatabase() {
245 if (!metadata_database_)
246 return scoped_ptr<base::ListValue>();
247 return metadata_database_->DumpDatabase();
250 void SyncEngine::SetSyncEnabled(bool enabled) {
251 if (sync_enabled_ == enabled)
252 return;
254 RemoteServiceState old_state = GetCurrentState();
255 sync_enabled_ = enabled;
256 if (old_state == GetCurrentState())
257 return;
259 const char* status_message = enabled ? "Sync is enabled" : "Sync is disabled";
260 FOR_EACH_OBSERVER(
261 Observer, service_observers_,
262 OnRemoteServiceStateUpdated(GetCurrentState(), status_message));
265 SyncStatusCode SyncEngine::SetConflictResolutionPolicy(
266 ConflictResolutionPolicy policy) {
267 conflict_resolution_policy_ = policy;
268 return SYNC_STATUS_OK;
271 ConflictResolutionPolicy
272 SyncEngine::GetConflictResolutionPolicy() const {
273 return conflict_resolution_policy_;
276 void SyncEngine::GetRemoteVersions(
277 const fileapi::FileSystemURL& url,
278 const RemoteVersionsCallback& callback) {
279 // TODO(tzik): Implement this before we support manual conflict resolution.
280 callback.Run(SYNC_STATUS_FAILED, std::vector<Version>());
283 void SyncEngine::DownloadRemoteVersion(
284 const fileapi::FileSystemURL& url,
285 const std::string& version_id,
286 const DownloadVersionCallback& callback) {
287 // TODO(tzik): Implement this before we support manual conflict resolution.
288 callback.Run(SYNC_STATUS_FAILED, webkit_blob::ScopedFile());
291 void SyncEngine::PromoteDemotedChanges() {
292 metadata_database_->PromoteLowerPriorityTrackersToNormal();
295 void SyncEngine::ApplyLocalChange(
296 const FileChange& local_change,
297 const base::FilePath& local_path,
298 const SyncFileMetadata& local_metadata,
299 const fileapi::FileSystemURL& url,
300 const SyncStatusCallback& callback) {
301 LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer(
302 this, local_metadata, local_change, local_path, url);
303 task_manager_->ScheduleSyncTask(
304 scoped_ptr<SyncTask>(syncer),
305 base::Bind(&SyncEngine::DidApplyLocalChange,
306 weak_ptr_factory_.GetWeakPtr(),
307 syncer, callback));
310 void SyncEngine::MaybeScheduleNextTask() {
311 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
312 return;
314 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated.
315 // TODO(tzik): Add an interface to get the number of dirty trackers to
316 // MetadataDatabase.
318 MaybeStartFetchChanges();
321 void SyncEngine::NotifyLastOperationStatus(
322 SyncStatusCode sync_status,
323 bool used_network) {
324 UpdateServiceStateFromSyncStatusCode(sync_status, used_network);
325 if (metadata_database_) {
326 FOR_EACH_OBSERVER(
327 Observer,
328 service_observers_,
329 OnRemoteChangeQueueUpdated(
330 metadata_database_->GetDirtyTrackerCount()));
334 void SyncEngine::OnNotificationReceived() {
335 if (service_state_ == REMOTE_SERVICE_TEMPORARY_UNAVAILABLE)
336 UpdateServiceState(REMOTE_SERVICE_OK, "Got push notification for Drive.");
338 should_check_remote_change_ = true;
339 MaybeScheduleNextTask();
342 void SyncEngine::OnPushNotificationEnabled(bool enabled) {}
344 void SyncEngine::OnReadyToSendRequests() {
345 if (service_state_ == REMOTE_SERVICE_OK)
346 return;
347 UpdateServiceState(REMOTE_SERVICE_OK, "Authenticated");
349 if (!metadata_database_ && auth_token_service_) {
350 drive_service_->Initialize(auth_token_service_->GetPrimaryAccountId());
351 PostInitializeTask();
352 return;
355 should_check_remote_change_ = true;
356 MaybeScheduleNextTask();
359 void SyncEngine::OnRefreshTokenInvalid() {
360 UpdateServiceState(
361 REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
362 "Found invalid refresh token.");
365 void SyncEngine::OnNetworkChanged(
366 net::NetworkChangeNotifier::ConnectionType type) {
367 bool new_network_availability =
368 type != net::NetworkChangeNotifier::CONNECTION_NONE;
370 if (network_available_ && !new_network_availability) {
371 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, "Disconnected");
372 } else if (!network_available_ && new_network_availability) {
373 UpdateServiceState(REMOTE_SERVICE_OK, "Connected");
374 should_check_remote_change_ = true;
375 MaybeStartFetchChanges();
377 network_available_ = new_network_availability;
380 drive::DriveServiceInterface* SyncEngine::GetDriveService() {
381 return drive_service_.get();
384 drive::DriveUploaderInterface* SyncEngine::GetDriveUploader() {
385 return drive_uploader_.get();
388 MetadataDatabase* SyncEngine::GetMetadataDatabase() {
389 return metadata_database_.get();
392 RemoteChangeProcessor* SyncEngine::GetRemoteChangeProcessor() {
393 return remote_change_processor_;
396 base::SequencedTaskRunner* SyncEngine::GetBlockingTaskRunner() {
397 return task_runner_.get();
400 SyncEngine::SyncEngine(
401 const base::FilePath& base_dir,
402 base::SequencedTaskRunner* task_runner,
403 scoped_ptr<drive::DriveServiceInterface> drive_service,
404 scoped_ptr<drive::DriveUploaderInterface> drive_uploader,
405 drive::DriveNotificationManager* notification_manager,
406 ExtensionServiceInterface* extension_service,
407 ProfileOAuth2TokenService* auth_token_service)
408 : base_dir_(base_dir),
409 task_runner_(task_runner),
410 drive_service_(drive_service.Pass()),
411 drive_uploader_(drive_uploader.Pass()),
412 notification_manager_(notification_manager),
413 extension_service_(extension_service),
414 auth_token_service_(auth_token_service),
415 remote_change_processor_(NULL),
416 service_state_(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE),
417 should_check_conflict_(true),
418 should_check_remote_change_(true),
419 listing_remote_changes_(false),
420 sync_enabled_(false),
421 conflict_resolution_policy_(CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN),
422 network_available_(false),
423 weak_ptr_factory_(this) {
426 void SyncEngine::DoDisableApp(const std::string& app_id,
427 const SyncStatusCallback& callback) {
428 metadata_database_->DisableApp(app_id, callback);
431 void SyncEngine::DoEnableApp(const std::string& app_id,
432 const SyncStatusCallback& callback) {
433 metadata_database_->EnableApp(app_id, callback);
436 void SyncEngine::PostInitializeTask() {
437 DCHECK(!metadata_database_);
439 // This initializer task may not run if metadata_database_ is already
440 // initialized when it runs.
441 SyncEngineInitializer* initializer =
442 new SyncEngineInitializer(this,
443 task_runner_.get(),
444 drive_service_.get(),
445 base_dir_.Append(kDatabaseName));
446 task_manager_->ScheduleSyncTaskAtPriority(
447 scoped_ptr<SyncTask>(initializer),
448 SyncTaskManager::PRIORITY_HIGH,
449 base::Bind(&SyncEngine::DidInitialize, weak_ptr_factory_.GetWeakPtr(),
450 initializer));
453 void SyncEngine::DidInitialize(SyncEngineInitializer* initializer,
454 SyncStatusCode status) {
455 if (status != SYNC_STATUS_OK) {
456 if (drive_service_->HasRefreshToken()) {
457 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
458 "Could not initialize remote service");
459 } else {
460 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
461 "Authentication required.");
463 return;
466 scoped_ptr<MetadataDatabase> metadata_database =
467 initializer->PassMetadataDatabase();
468 if (metadata_database)
469 metadata_database_ = metadata_database.Pass();
471 DCHECK(metadata_database_);
472 UpdateRegisteredApps();
475 void SyncEngine::DidProcessRemoteChange(RemoteToLocalSyncer* syncer,
476 const SyncFileCallback& callback,
477 SyncStatusCode status) {
478 if (syncer->is_sync_root_deletion()) {
479 MetadataDatabase::ClearDatabase(metadata_database_.Pass());
480 PostInitializeTask();
481 callback.Run(status, syncer->url());
482 return;
485 if (status == SYNC_STATUS_OK) {
486 if (syncer->sync_action() != SYNC_ACTION_NONE &&
487 syncer->url().is_valid()) {
488 FOR_EACH_OBSERVER(FileStatusObserver,
489 file_status_observers_,
490 OnFileStatusChanged(syncer->url(),
491 SYNC_FILE_STATUS_SYNCED,
492 syncer->sync_action(),
493 SYNC_DIRECTION_REMOTE_TO_LOCAL));
496 if (syncer->sync_action() == SYNC_ACTION_DELETED &&
497 syncer->url().is_valid() &&
498 fileapi::VirtualPath::IsRootPath(syncer->url().path())) {
499 RegisterOrigin(syncer->url().origin(), base::Bind(&EmptyStatusCallback));
501 should_check_conflict_ = true;
503 callback.Run(status, syncer->url());
506 void SyncEngine::DidApplyLocalChange(LocalToRemoteSyncer* syncer,
507 const SyncStatusCallback& callback,
508 SyncStatusCode status) {
509 if ((status == SYNC_STATUS_OK || status == SYNC_STATUS_RETRY) &&
510 syncer->url().is_valid() &&
511 syncer->sync_action() != SYNC_ACTION_NONE) {
512 fileapi::FileSystemURL updated_url = syncer->url();
513 if (!syncer->target_path().empty()) {
514 updated_url = CreateSyncableFileSystemURL(syncer->url().origin(),
515 syncer->target_path());
517 FOR_EACH_OBSERVER(FileStatusObserver,
518 file_status_observers_,
519 OnFileStatusChanged(updated_url,
520 SYNC_FILE_STATUS_SYNCED,
521 syncer->sync_action(),
522 SYNC_DIRECTION_LOCAL_TO_REMOTE));
525 if (status == SYNC_STATUS_UNKNOWN_ORIGIN && syncer->url().is_valid()) {
526 RegisterOrigin(syncer->url().origin(),
527 base::Bind(&EmptyStatusCallback));
530 if (syncer->needs_remote_change_listing() &&
531 !listing_remote_changes_) {
532 task_manager_->ScheduleSyncTaskAtPriority(
533 scoped_ptr<SyncTask>(new ListChangesTask(this)),
534 SyncTaskManager::PRIORITY_HIGH,
535 base::Bind(&SyncEngine::DidFetchChanges,
536 weak_ptr_factory_.GetWeakPtr()));
537 should_check_remote_change_ = false;
538 listing_remote_changes_ = true;
539 time_to_check_changes_ =
540 base::TimeTicks::Now() +
541 base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
544 if (status != SYNC_STATUS_OK &&
545 status != SYNC_STATUS_NO_CHANGE_TO_SYNC) {
546 callback.Run(status);
547 return;
550 if (status == SYNC_STATUS_OK)
551 should_check_conflict_ = true;
553 callback.Run(status);
556 void SyncEngine::MaybeStartFetchChanges() {
557 if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
558 return;
560 if (!metadata_database_)
561 return;
563 if (listing_remote_changes_)
564 return;
566 base::TimeTicks now = base::TimeTicks::Now();
567 if (!should_check_remote_change_ && now < time_to_check_changes_) {
568 if (!metadata_database_->HasDirtyTracker() && should_check_conflict_) {
569 task_manager_->ScheduleSyncTaskIfIdle(
570 scoped_ptr<SyncTask>(new ConflictResolver(this)),
571 base::Bind(&SyncEngine::DidResolveConflict,
572 weak_ptr_factory_.GetWeakPtr()));
574 return;
577 if (task_manager_->ScheduleSyncTaskIfIdle(
578 scoped_ptr<SyncTask>(new ListChangesTask(this)),
579 base::Bind(&SyncEngine::DidFetchChanges,
580 weak_ptr_factory_.GetWeakPtr()))) {
581 should_check_remote_change_ = false;
582 listing_remote_changes_ = true;
583 time_to_check_changes_ =
584 now + base::TimeDelta::FromSeconds(kListChangesRetryDelaySeconds);
588 void SyncEngine::DidResolveConflict(SyncStatusCode status) {
589 if (status == SYNC_STATUS_NO_CONFLICT)
590 should_check_conflict_ = false;
593 void SyncEngine::DidFetchChanges(SyncStatusCode status) {
594 if (status == SYNC_STATUS_OK)
595 should_check_conflict_ = true;
596 listing_remote_changes_ = false;
599 void SyncEngine::UpdateServiceStateFromSyncStatusCode(
600 SyncStatusCode status,
601 bool used_network) {
602 switch (status) {
603 case SYNC_STATUS_OK:
604 if (used_network)
605 UpdateServiceState(REMOTE_SERVICE_OK, std::string());
606 break;
608 // Authentication error.
609 case SYNC_STATUS_AUTHENTICATION_FAILED:
610 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
611 "Authentication required");
612 break;
614 // OAuth token error.
615 case SYNC_STATUS_ACCESS_FORBIDDEN:
616 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
617 "Access forbidden");
618 break;
620 // Errors which could make the service temporarily unavailable.
621 case SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE:
622 case SYNC_STATUS_NETWORK_ERROR:
623 case SYNC_STATUS_ABORT:
624 case SYNC_STATUS_FAILED:
625 if (drive_service_->HasRefreshToken()) {
626 UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
627 "Network or temporary service error.");
628 } else {
629 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
630 "Authentication required");
632 break;
634 // Errors which would require manual user intervention to resolve.
635 case SYNC_DATABASE_ERROR_CORRUPTION:
636 case SYNC_DATABASE_ERROR_IO_ERROR:
637 case SYNC_DATABASE_ERROR_FAILED:
638 UpdateServiceState(REMOTE_SERVICE_DISABLED,
639 "Unrecoverable database error");
640 break;
642 default:
643 // Other errors don't affect service state
644 break;
648 void SyncEngine::UpdateServiceState(RemoteServiceState state,
649 const std::string& description) {
650 RemoteServiceState old_state = GetCurrentState();
651 service_state_ = state;
653 if (old_state == GetCurrentState())
654 return;
656 util::Log(logging::LOG_INFO, FROM_HERE,
657 "Service state changed: %d->%d: %s",
658 old_state, GetCurrentState(), description.c_str());
659 FOR_EACH_OBSERVER(
660 Observer, service_observers_,
661 OnRemoteServiceStateUpdated(GetCurrentState(), description));
664 void SyncEngine::UpdateRegisteredApps() {
665 if (!extension_service_)
666 return;
668 DCHECK(metadata_database_);
669 std::vector<std::string> app_ids;
670 metadata_database_->GetRegisteredAppIDs(&app_ids);
672 // Update the status of every origin using status from ExtensionService.
673 for (std::vector<std::string>::const_iterator itr = app_ids.begin();
674 itr != app_ids.end(); ++itr) {
675 const std::string& app_id = *itr;
676 GURL origin =
677 extensions::Extension::GetBaseURLFromExtensionId(app_id);
678 if (!extension_service_->GetInstalledExtension(app_id)) {
679 // Extension has been uninstalled.
680 // (At this stage we can't know if it was unpacked extension or not,
681 // so just purge the remote folder.)
682 UninstallOrigin(origin,
683 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
684 base::Bind(&EmptyStatusCallback));
685 continue;
687 FileTracker tracker;
688 if (!metadata_database_->FindAppRootTracker(app_id, &tracker)) {
689 // App will register itself on first run.
690 continue;
692 bool is_app_enabled = extension_service_->IsExtensionEnabled(app_id);
693 bool is_app_root_tracker_enabled =
694 tracker.tracker_kind() == TRACKER_KIND_APP_ROOT;
695 if (is_app_enabled && !is_app_root_tracker_enabled)
696 EnableOrigin(origin, base::Bind(&EmptyStatusCallback));
697 else if (!is_app_enabled && is_app_root_tracker_enabled)
698 DisableOrigin(origin, base::Bind(&EmptyStatusCallback));
702 } // namespace drive_backend
703 } // namespace sync_file_system