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"
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
{
47 void EmptyStatusCallback(SyncStatusCode status
) {}
51 scoped_ptr
<SyncEngine
> SyncEngine::CreateForBrowserContext(
52 content::BrowserContext
* context
) {
54 google_apis::DriveApiUrlGenerator::kBaseUrlForProduction
);
55 GURL
base_download_url(
56 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction
);
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(
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(
95 GetSyncFileSystemDir(context
->GetPath()),
98 drive_uploader
.Pass(),
102 sync_engine
->Initialize();
104 return sync_engine
.Pass();
107 void SyncEngine::AppendDependsOnFactories(
108 std::set
<BrowserContextKeyedServiceFactory
*>* 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();
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(
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
,
160 void SyncEngine::EnableOrigin(
162 const SyncStatusCallback
& callback
) {
163 task_manager_
->ScheduleTaskAtPriority(
164 base::Bind(&SyncEngine::DoEnableApp
,
165 weak_ptr_factory_
.GetWeakPtr(),
167 SyncTaskManager::PRIORITY_HIGH
,
171 void SyncEngine::DisableOrigin(
173 const SyncStatusCallback
& callback
) {
174 task_manager_
->ScheduleTaskAtPriority(
175 base::Bind(&SyncEngine::DoDisableApp
,
176 weak_ptr_factory_
.GetWeakPtr(),
178 SyncTaskManager::PRIORITY_HIGH
,
182 void SyncEngine::UninstallOrigin(
185 const SyncStatusCallback
& callback
) {
186 task_manager_
->ScheduleSyncTaskAtPriority(
187 scoped_ptr
<SyncTask
>(new UninstallAppTask(this, origin
.host(), flag
)),
188 SyncTaskManager::PRIORITY_HIGH
,
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(),
202 void SyncEngine::SetRemoteChangeProcessor(
203 RemoteChangeProcessor
* processor
) {
204 remote_change_processor_
= processor
;
207 LocalChangeProcessor
* SyncEngine::GetLocalChangeProcessor() {
211 bool SyncEngine::IsConflicting(const fileapi::FileSystemURL
& url
) {
212 // TODO(tzik): Implement this before we support manual conflict resolution.
216 RemoteServiceState
SyncEngine::GetCurrentState() const {
217 return service_state_
;
220 void SyncEngine::GetOriginStatusMap(OriginStatusMap
* status_map
) {
222 if (!extension_service_
|| !metadata_database_
)
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
;
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
)
254 RemoteServiceState old_state
= GetCurrentState();
255 sync_enabled_
= enabled
;
256 if (old_state
== GetCurrentState())
259 const char* status_message
= enabled
? "Sync is enabled" : "Sync is disabled";
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(),
310 void SyncEngine::MaybeScheduleNextTask() {
311 if (GetCurrentState() == REMOTE_SERVICE_DISABLED
)
314 // TODO(tzik): Notify observer of OnRemoteChangeQueueUpdated.
315 // TODO(tzik): Add an interface to get the number of dirty trackers to
318 MaybeStartFetchChanges();
321 void SyncEngine::NotifyLastOperationStatus(
322 SyncStatusCode sync_status
,
324 UpdateServiceStateFromSyncStatusCode(sync_status
, used_network
);
325 if (metadata_database_
) {
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
)
347 UpdateServiceState(REMOTE_SERVICE_OK
, "Authenticated");
349 if (!metadata_database_
&& auth_token_service_
) {
350 drive_service_
->Initialize(auth_token_service_
->GetPrimaryAccountId());
351 PostInitializeTask();
355 should_check_remote_change_
= true;
356 MaybeScheduleNextTask();
359 void SyncEngine::OnRefreshTokenInvalid() {
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,
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(),
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");
460 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED
,
461 "Authentication required.");
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());
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
);
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
)
560 if (!metadata_database_
)
563 if (listing_remote_changes_
)
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()));
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
,
605 UpdateServiceState(REMOTE_SERVICE_OK
, std::string());
608 // Authentication error.
609 case SYNC_STATUS_AUTHENTICATION_FAILED
:
610 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED
,
611 "Authentication required");
614 // OAuth token error.
615 case SYNC_STATUS_ACCESS_FORBIDDEN
:
616 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED
,
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.");
629 UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED
,
630 "Authentication required");
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");
643 // Other errors don't affect service state
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())
656 util::Log(logging::LOG_INFO
, FROM_HERE
,
657 "Service state changed: %d->%d: %s",
658 old_state
, GetCurrentState(), description
.c_str());
660 Observer
, service_observers_
,
661 OnRemoteServiceStateUpdated(GetCurrentState(), description
));
664 void SyncEngine::UpdateRegisteredApps() {
665 if (!extension_service_
)
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
;
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
));
688 if (!metadata_database_
->FindAppRootTracker(app_id
, &tracker
)) {
689 // App will register itself on first run.
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