1 // Copyright (c) 2012 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/sync_file_system_service.h"
10 #include "base/format_macros.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/metrics/histogram.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/stl_util.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
18 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/sync/profile_sync_service.h"
21 #include "chrome/browser/sync/profile_sync_service_factory.h"
22 #include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
23 #include "chrome/browser/sync_file_system/logger.h"
24 #include "chrome/browser/sync_file_system/sync_direction.h"
25 #include "chrome/browser/sync_file_system/sync_event_observer.h"
26 #include "chrome/browser/sync_file_system/sync_file_metadata.h"
27 #include "chrome/browser/sync_file_system/sync_process_runner.h"
28 #include "chrome/browser/sync_file_system/sync_status_code.h"
29 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
30 #include "components/keyed_service/content/browser_context_dependency_manager.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/storage_partition.h"
33 #include "extensions/browser/extension_prefs.h"
34 #include "extensions/browser/extension_registry.h"
35 #include "extensions/common/extension.h"
36 #include "extensions/common/manifest_constants.h"
38 #include "webkit/browser/fileapi/file_system_context.h"
40 using content::BrowserThread
;
41 using extensions::Extension
;
42 using extensions::ExtensionPrefs
;
43 using extensions::ExtensionRegistry
;
44 using storage::FileSystemURL
;
45 using storage::FileSystemURLSet
;
47 namespace sync_file_system
{
51 const char kLocalSyncName
[] = "Local sync";
52 const char kRemoteSyncName
[] = "Remote sync";
54 SyncServiceState
RemoteStateToSyncServiceState(
55 RemoteServiceState state
) {
57 case REMOTE_SERVICE_OK
:
58 return SYNC_SERVICE_RUNNING
;
59 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
:
60 return SYNC_SERVICE_TEMPORARY_UNAVAILABLE
;
61 case REMOTE_SERVICE_AUTHENTICATION_REQUIRED
:
62 return SYNC_SERVICE_AUTHENTICATION_REQUIRED
;
63 case REMOTE_SERVICE_ACCESS_FORBIDDEN
:
64 return SYNC_SERVICE_TEMPORARY_UNAVAILABLE
;
65 case REMOTE_SERVICE_DISABLED
:
66 return SYNC_SERVICE_DISABLED
;
67 case REMOTE_SERVICE_STATE_MAX
:
70 NOTREACHED() << "Unknown remote service state: " << state
;
71 return SYNC_SERVICE_DISABLED
;
74 void DidHandleUninstalledEvent(const GURL
& origin
, SyncStatusCode code
) {
75 if (code
!= SYNC_STATUS_OK
&& code
!= SYNC_STATUS_UNKNOWN_ORIGIN
) {
76 util::Log(logging::LOG_WARNING
, FROM_HERE
,
77 "Failed to uninstall origin for uninstall event: %s",
78 origin
.spec().c_str());
82 void DidHandleUnloadedEvent(const GURL
& origin
, SyncStatusCode code
) {
83 if (code
!= SYNC_STATUS_OK
&& code
!= SYNC_STATUS_UNKNOWN_ORIGIN
) {
84 util::Log(logging::LOG_WARNING
, FROM_HERE
,
85 "Failed to disable origin for unload event: %s",
86 origin
.spec().c_str());
90 void DidHandleLoadEvent(
92 SyncStatusCode code
) {
93 if (code
!= SYNC_STATUS_OK
) {
94 util::Log(logging::LOG_WARNING
, FROM_HERE
,
95 "Failed to enable origin for load event: %s",
96 origin
.spec().c_str());
100 std::string
SyncFileStatusToString(SyncFileStatus sync_file_status
) {
101 return extensions::api::sync_file_system::ToString(
102 extensions::SyncFileStatusToExtensionEnum(sync_file_status
));
105 // Gets called repeatedly until every SyncFileStatus has been mapped.
106 void DidGetFileSyncStatusForDump(
107 base::ListValue
* files
,
109 const SyncFileSystemService::DumpFilesCallback
& callback
,
110 base::DictionaryValue
* file
,
111 SyncStatusCode sync_status_code
,
112 SyncFileStatus sync_file_status
) {
117 file
->SetString("status", SyncFileStatusToString(sync_file_status
));
119 // Once all results have been received, run the callback to signal end.
120 DCHECK_LE(*num_results
, files
->GetSize());
121 if (++*num_results
< files
->GetSize())
124 callback
.Run(*files
);
127 // We need this indirection because WeakPtr can only be bound to methods
128 // without a return value.
129 LocalChangeProcessor
* GetLocalChangeProcessorAdapter(
130 base::WeakPtr
<SyncFileSystemService
> service
,
131 const GURL
& origin
) {
134 return service
->GetLocalChangeProcessor(origin
);
139 //---------------------------------------------------------------------------
140 // SyncProcessRunner's.
142 // SyncProcessRunner implementation for LocalSync.
143 class LocalSyncRunner
: public SyncProcessRunner
,
144 public LocalFileSyncService::Observer
{
146 LocalSyncRunner(const std::string
& name
,
147 SyncFileSystemService
* sync_service
)
148 : SyncProcessRunner(name
, sync_service
,
149 scoped_ptr
<SyncProcessRunner::TimerHelper
>(), 1),
152 virtual void StartSync(const SyncStatusCallback
& callback
) OVERRIDE
{
153 GetSyncService()->local_service_
->ProcessLocalChange(
154 base::Bind(&LocalSyncRunner::DidProcessLocalChange
,
155 factory_
.GetWeakPtr(), callback
));
158 // LocalFileSyncService::Observer overrides.
159 virtual void OnLocalChangeAvailable(int64 pending_changes
) OVERRIDE
{
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
162 OnChangesUpdated(pending_changes
);
164 // Kick other sync runners just in case they're not running.
165 GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
169 void DidProcessLocalChange(
170 const SyncStatusCallback
& callback
,
171 SyncStatusCode status
,
172 const FileSystemURL
& url
) {
173 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
174 "ProcessLocalChange finished with status=%d (%s) for url=%s",
175 status
, SyncStatusCodeToString(status
),
176 url
.DebugString().c_str());
177 callback
.Run(status
);
180 base::WeakPtrFactory
<LocalSyncRunner
> factory_
;
181 DISALLOW_COPY_AND_ASSIGN(LocalSyncRunner
);
184 // SyncProcessRunner implementation for RemoteSync.
185 class RemoteSyncRunner
: public SyncProcessRunner
,
186 public RemoteFileSyncService::Observer
{
188 RemoteSyncRunner(const std::string
& name
,
189 SyncFileSystemService
* sync_service
,
190 RemoteFileSyncService
* remote_service
)
191 : SyncProcessRunner(name
, sync_service
,
192 scoped_ptr
<SyncProcessRunner::TimerHelper
>(), 1),
193 remote_service_(remote_service
),
194 last_state_(REMOTE_SERVICE_OK
),
197 virtual void StartSync(const SyncStatusCallback
& callback
) OVERRIDE
{
198 remote_service_
->ProcessRemoteChange(
199 base::Bind(&RemoteSyncRunner::DidProcessRemoteChange
,
200 factory_
.GetWeakPtr(), callback
));
203 virtual SyncServiceState
GetServiceState() OVERRIDE
{
204 return RemoteStateToSyncServiceState(last_state_
);
207 // RemoteFileSyncService::Observer overrides.
208 virtual void OnRemoteChangeQueueUpdated(int64 pending_changes
) OVERRIDE
{
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
211 OnChangesUpdated(pending_changes
);
213 // Kick other sync runners just in case they're not running.
214 GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
217 virtual void OnRemoteServiceStateUpdated(
218 RemoteServiceState state
,
219 const std::string
& description
) OVERRIDE
{
220 // Just forward to SyncFileSystemService.
221 GetSyncService()->OnRemoteServiceStateUpdated(state
, description
);
226 void DidProcessRemoteChange(
227 const SyncStatusCallback
& callback
,
228 SyncStatusCode status
,
229 const FileSystemURL
& url
) {
230 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
231 "ProcessRemoteChange finished with status=%d (%s) for url=%s",
232 status
, SyncStatusCodeToString(status
),
233 url
.DebugString().c_str());
235 if (status
== SYNC_STATUS_FILE_BUSY
) {
236 GetSyncService()->local_service_
->RegisterURLForWaitingSync(
237 url
, base::Bind(&RemoteSyncRunner::Schedule
,
238 factory_
.GetWeakPtr()));
240 callback
.Run(status
);
243 RemoteFileSyncService
* remote_service_
;
244 RemoteServiceState last_state_
;
245 base::WeakPtrFactory
<RemoteSyncRunner
> factory_
;
246 DISALLOW_COPY_AND_ASSIGN(RemoteSyncRunner
);
249 //-----------------------------------------------------------------------------
250 // SyncFileSystemService
252 void SyncFileSystemService::Shutdown() {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
255 local_sync_runners_
.clear();
256 remote_sync_runners_
.clear();
258 local_service_
->Shutdown();
259 local_service_
.reset();
261 remote_service_
.reset();
263 ProfileSyncServiceBase
* profile_sync_service
=
264 ProfileSyncServiceFactory::GetForProfile(profile_
);
265 if (profile_sync_service
)
266 profile_sync_service
->RemoveObserver(this);
268 ExtensionRegistry::Get(profile_
)->RemoveObserver(this);
273 SyncFileSystemService::~SyncFileSystemService() {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
278 void SyncFileSystemService::InitializeForApp(
279 storage::FileSystemContext
* file_system_context
,
280 const GURL
& app_origin
,
281 const SyncStatusCallback
& callback
) {
282 DCHECK(local_service_
);
283 DCHECK(remote_service_
);
284 DCHECK(app_origin
== app_origin
.GetOrigin());
286 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
287 "Initializing for App: %s", app_origin
.spec().c_str());
289 local_service_
->MaybeInitializeFileSystemContext(
290 app_origin
, file_system_context
,
291 base::Bind(&SyncFileSystemService::DidInitializeFileSystem
,
292 AsWeakPtr(), app_origin
, callback
));
295 void SyncFileSystemService::GetExtensionStatusMap(
296 const ExtensionStatusMapCallback
& callback
) {
297 remote_service_
->GetOriginStatusMap(
298 base::Bind(&SyncFileSystemService::DidGetExtensionStatusMap
,
299 AsWeakPtr(), callback
));
302 void SyncFileSystemService::DumpFiles(const GURL
& origin
,
303 const DumpFilesCallback
& callback
) {
304 DCHECK(!origin
.is_empty());
306 content::StoragePartition
* storage_partition
=
307 content::BrowserContext::GetStoragePartitionForSite(profile_
, origin
);
308 storage::FileSystemContext
* file_system_context
=
309 storage_partition
->GetFileSystemContext();
310 local_service_
->MaybeInitializeFileSystemContext(
311 origin
, file_system_context
,
312 base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump
,
313 AsWeakPtr(), origin
, callback
));
316 void SyncFileSystemService::DumpDatabase(const DumpFilesCallback
& callback
) {
317 remote_service_
->DumpDatabase(
318 base::Bind(&SyncFileSystemService::DidDumpDatabase
,
319 AsWeakPtr(), callback
));
322 void SyncFileSystemService::GetFileSyncStatus(
323 const FileSystemURL
& url
, const SyncFileStatusCallback
& callback
) {
324 DCHECK(local_service_
);
325 DCHECK(GetRemoteService(url
.origin()));
327 // It's possible to get an invalid FileEntry.
328 if (!url
.is_valid()) {
329 base::ThreadTaskRunnerHandle::Get()->PostTask(
332 SYNC_FILE_ERROR_INVALID_URL
,
333 SYNC_FILE_STATUS_UNKNOWN
));
337 local_service_
->HasPendingLocalChanges(
339 base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus
,
340 AsWeakPtr(), callback
));
343 void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver
* observer
) {
344 observers_
.AddObserver(observer
);
347 void SyncFileSystemService::RemoveSyncEventObserver(
348 SyncEventObserver
* observer
) {
349 observers_
.RemoveObserver(observer
);
352 LocalChangeProcessor
* SyncFileSystemService::GetLocalChangeProcessor(
353 const GURL
& origin
) {
354 return GetRemoteService(origin
)->GetLocalChangeProcessor();
357 void SyncFileSystemService::OnSyncIdle() {
358 if (promoting_demoted_changes_
)
360 promoting_demoted_changes_
= true;
362 int* job_count
= new int(1);
363 base::Closure promote_completion_callback
=
364 base::Bind(&SyncFileSystemService::OnPromotionCompleted
,
365 AsWeakPtr(), base::Owned(job_count
));
367 int64 remote_changes
= 0;
368 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
)
369 remote_changes
+= remote_sync_runners_
[i
]->pending_changes();
370 if (remote_changes
== 0) {
372 local_service_
->PromoteDemotedChanges(promote_completion_callback
);
375 int64 local_changes
= 0;
376 for (size_t i
= 0; i
< local_sync_runners_
.size(); ++i
)
377 local_changes
+= local_sync_runners_
[i
]->pending_changes();
378 if (local_changes
== 0) {
380 remote_service_
->PromoteDemotedChanges(promote_completion_callback
);
383 promote_completion_callback
.Run();
386 void SyncFileSystemService::OnPromotionCompleted(int* count
) {
389 promoting_demoted_changes_
= false;
393 void SyncFileSystemService::CheckIfIdle() {
394 if (promoting_demoted_changes_
)
397 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
) {
398 SyncServiceState service_state
= remote_sync_runners_
[i
]->GetServiceState();
399 if (service_state
!= SYNC_SERVICE_RUNNING
&&
400 service_state
!= SYNC_SERVICE_TEMPORARY_UNAVAILABLE
)
403 if (remote_sync_runners_
[i
]->pending_changes())
407 for (size_t i
= 0; i
< local_sync_runners_
.size(); ++i
) {
408 SyncServiceState service_state
= local_sync_runners_
[i
]->GetServiceState();
409 if (service_state
!= SYNC_SERVICE_RUNNING
&&
410 service_state
!= SYNC_SERVICE_TEMPORARY_UNAVAILABLE
)
413 if (local_sync_runners_
[i
]->pending_changes())
417 if (idle_callback_
.is_null())
420 base::Closure callback
= idle_callback_
;
421 idle_callback_
.Reset();
425 SyncServiceState
SyncFileSystemService::GetSyncServiceState() {
426 // For now we always query the state from the main RemoteFileSyncService.
427 return RemoteStateToSyncServiceState(remote_service_
->GetCurrentState());
430 SyncFileSystemService
* SyncFileSystemService::GetSyncService() {
434 void SyncFileSystemService::CallOnIdleForTesting(
435 const base::Closure
& callback
) {
436 DCHECK(idle_callback_
.is_null());
437 idle_callback_
= callback
;
441 SyncFileSystemService::SyncFileSystemService(Profile
* profile
)
444 promoting_demoted_changes_(false) {
447 void SyncFileSystemService::Initialize(
448 scoped_ptr
<LocalFileSyncService
> local_service
,
449 scoped_ptr
<RemoteFileSyncService
> remote_service
) {
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
451 DCHECK(local_service
);
452 DCHECK(remote_service
);
455 local_service_
= local_service
.Pass();
456 remote_service_
= remote_service
.Pass();
458 scoped_ptr
<LocalSyncRunner
> local_syncer(
459 new LocalSyncRunner(kLocalSyncName
, this));
460 scoped_ptr
<RemoteSyncRunner
> remote_syncer(
461 new RemoteSyncRunner(kRemoteSyncName
, this, remote_service_
.get()));
463 local_service_
->AddChangeObserver(local_syncer
.get());
464 local_service_
->SetLocalChangeProcessorCallback(
465 base::Bind(&GetLocalChangeProcessorAdapter
, AsWeakPtr()));
467 remote_service_
->AddServiceObserver(remote_syncer
.get());
468 remote_service_
->AddFileStatusObserver(this);
469 remote_service_
->SetRemoteChangeProcessor(local_service_
.get());
471 local_sync_runners_
.push_back(local_syncer
.release());
472 remote_sync_runners_
.push_back(remote_syncer
.release());
474 ProfileSyncServiceBase
* profile_sync_service
=
475 ProfileSyncServiceFactory::GetForProfile(profile_
);
476 if (profile_sync_service
) {
477 UpdateSyncEnabledStatus(profile_sync_service
);
478 profile_sync_service
->AddObserver(this);
481 ExtensionRegistry::Get(profile_
)->AddObserver(this);
484 void SyncFileSystemService::DidInitializeFileSystem(
485 const GURL
& app_origin
,
486 const SyncStatusCallback
& callback
,
487 SyncStatusCode status
) {
488 DVLOG(1) << "DidInitializeFileSystem: "
489 << app_origin
.spec() << " " << status
;
491 if (status
!= SYNC_STATUS_OK
) {
492 callback
.Run(status
);
496 // Local side of initialization for the app is done.
497 // Continue on initializing the remote side.
498 GetRemoteService(app_origin
)->RegisterOrigin(
500 base::Bind(&SyncFileSystemService::DidRegisterOrigin
,
501 AsWeakPtr(), app_origin
, callback
));
504 void SyncFileSystemService::DidRegisterOrigin(
505 const GURL
& app_origin
,
506 const SyncStatusCallback
& callback
,
507 SyncStatusCode status
) {
508 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
509 "DidInitializeForApp (registered the origin): %s: %s",
510 app_origin
.spec().c_str(),
511 SyncStatusCodeToString(status
));
513 UMA_HISTOGRAM_ENUMERATION("SyncFileSystem.RegisterOriginResult",
514 GetRemoteService(app_origin
)->GetCurrentState(),
515 REMOTE_SERVICE_STATE_MAX
);
517 if (status
== SYNC_STATUS_FAILED
) {
518 // If we got generic error return the service status information.
519 switch (GetRemoteService(app_origin
)->GetCurrentState()) {
520 case REMOTE_SERVICE_AUTHENTICATION_REQUIRED
:
521 callback
.Run(SYNC_STATUS_AUTHENTICATION_FAILED
);
523 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
:
524 callback
.Run(SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE
);
531 callback
.Run(status
);
534 void SyncFileSystemService::DidInitializeFileSystemForDump(
536 const DumpFilesCallback
& callback
,
537 SyncStatusCode status
) {
538 DCHECK(!origin
.is_empty());
540 if (status
!= SYNC_STATUS_OK
) {
541 callback
.Run(base::ListValue());
545 GetRemoteService(origin
)->DumpFiles(
548 &SyncFileSystemService::DidDumpFiles
,
554 void SyncFileSystemService::DidDumpFiles(
556 const DumpFilesCallback
& callback
,
557 scoped_ptr
<base::ListValue
> dump_files
) {
558 if (!dump_files
|| !dump_files
->GetSize()) {
559 callback
.Run(base::ListValue());
563 base::ListValue
* files
= dump_files
.get();
564 base::Callback
<void(base::DictionaryValue
*,
566 SyncFileStatus
)> completion_callback
=
567 base::Bind(&DidGetFileSyncStatusForDump
,
568 base::Owned(dump_files
.release()),
569 base::Owned(new size_t(0)),
572 // After all metadata loaded, sync status can be added to each entry.
573 for (size_t i
= 0; i
< files
->GetSize(); ++i
) {
574 base::DictionaryValue
* file
= NULL
;
575 std::string path_string
;
576 if (!files
->GetDictionary(i
, &file
) ||
577 !file
->GetString("path", &path_string
)) {
579 completion_callback
.Run(
580 NULL
, SYNC_FILE_ERROR_FAILED
, SYNC_FILE_STATUS_UNKNOWN
);
584 base::FilePath file_path
= base::FilePath::FromUTF8Unsafe(path_string
);
585 FileSystemURL url
= CreateSyncableFileSystemURL(origin
, file_path
);
586 GetFileSyncStatus(url
, base::Bind(completion_callback
, file
));
590 void SyncFileSystemService::DidDumpDatabase(const DumpFilesCallback
& callback
,
591 scoped_ptr
<base::ListValue
> list
) {
593 list
= make_scoped_ptr(new base::ListValue
);
597 void SyncFileSystemService::DidGetExtensionStatusMap(
598 const ExtensionStatusMapCallback
& callback
,
599 scoped_ptr
<RemoteFileSyncService::OriginStatusMap
> status_map
) {
601 status_map
= make_scoped_ptr(new RemoteFileSyncService::OriginStatusMap
);
602 callback
.Run(*status_map
);
605 void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled
) {
606 sync_enabled_
= enabled
;
607 remote_service_
->SetSyncEnabled(sync_enabled_
);
610 void SyncFileSystemService::DidGetLocalChangeStatus(
611 const SyncFileStatusCallback
& callback
,
612 SyncStatusCode status
,
613 bool has_pending_local_changes
) {
616 has_pending_local_changes
?
617 SYNC_FILE_STATUS_HAS_PENDING_CHANGES
: SYNC_FILE_STATUS_SYNCED
);
620 void SyncFileSystemService::OnRemoteServiceStateUpdated(
621 RemoteServiceState state
,
622 const std::string
& description
) {
623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
624 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
625 "OnRemoteServiceStateChanged: %d %s", state
, description
.c_str());
628 SyncEventObserver
, observers_
,
629 OnSyncStateUpdated(GURL(),
630 RemoteStateToSyncServiceState(state
),
633 RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
636 void SyncFileSystemService::OnExtensionInstalled(
637 content::BrowserContext
* browser_context
,
638 const Extension
* extension
,
640 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
641 DVLOG(1) << "Handle extension notification for INSTALLED: " << app_origin
;
642 // NOTE: When an app is uninstalled and re-installed in a sequence,
643 // |local_service_| may still keeps |app_origin| as disabled origin.
644 local_service_
->SetOriginEnabled(app_origin
, true);
647 void SyncFileSystemService::OnExtensionUnloaded(
648 content::BrowserContext
* browser_context
,
649 const Extension
* extension
,
650 extensions::UnloadedExtensionInfo::Reason reason
) {
651 if (reason
!= extensions::UnloadedExtensionInfo::REASON_DISABLE
)
654 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
655 int disable_reasons
=
656 ExtensionPrefs::Get(profile_
)->GetDisableReasons(extension
->id());
657 if (disable_reasons
& Extension::DISABLE_RELOAD
) {
658 // Bypass disabling the origin since the app will be re-enabled soon.
659 // NOTE: If re-enabling the app fails, the app is disabled while it is
660 // handled as enabled origin in the SyncFS. This should be safe and will be
661 // recovered when the user re-enables the app manually or the sync service
663 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE_RELOAD): "
668 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
670 GetRemoteService(app_origin
)->DisableOrigin(
672 base::Bind(&DidHandleUnloadedEvent
, app_origin
));
673 local_service_
->SetOriginEnabled(app_origin
, false);
676 void SyncFileSystemService::OnExtensionUninstalled(
677 content::BrowserContext
* browser_context
,
678 const Extension
* extension
,
679 extensions::UninstallReason reason
) {
680 RemoteFileSyncService::UninstallFlag flag
=
681 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE
;
682 // If it's loaded from an unpacked package and with key: field,
683 // the uninstall will not be sync'ed and the user might be using the
684 // same app key in other installs, so avoid purging the remote folder.
685 if (extensions::Manifest::IsUnpackedLocation(extension
->location()) &&
686 extension
->manifest()->HasKey(extensions::manifest_keys::kKey
)) {
687 flag
= RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE
;
690 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
691 DVLOG(1) << "Handle extension notification for UNINSTALLED: "
693 GetRemoteService(app_origin
)->UninstallOrigin(
695 base::Bind(&DidHandleUninstalledEvent
, app_origin
));
696 local_service_
->SetOriginEnabled(app_origin
, false);
699 void SyncFileSystemService::OnExtensionLoaded(
700 content::BrowserContext
* browser_context
,
701 const Extension
* extension
) {
702 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
703 DVLOG(1) << "Handle extension notification for LOADED: " << app_origin
;
704 GetRemoteService(app_origin
)->EnableOrigin(
706 base::Bind(&DidHandleLoadEvent
, app_origin
));
707 local_service_
->SetOriginEnabled(app_origin
, true);
710 void SyncFileSystemService::OnStateChanged() {
711 ProfileSyncServiceBase
* profile_sync_service
=
712 ProfileSyncServiceFactory::GetForProfile(profile_
);
713 if (profile_sync_service
)
714 UpdateSyncEnabledStatus(profile_sync_service
);
717 void SyncFileSystemService::OnFileStatusChanged(
718 const FileSystemURL
& url
,
719 SyncFileStatus sync_status
,
720 SyncAction action_taken
,
721 SyncDirection direction
) {
723 SyncEventObserver
, observers_
,
724 OnFileSynced(url
, sync_status
, action_taken
, direction
));
727 void SyncFileSystemService::UpdateSyncEnabledStatus(
728 ProfileSyncServiceBase
* profile_sync_service
) {
729 if (!profile_sync_service
->HasSyncSetupCompleted())
731 bool old_sync_enabled
= sync_enabled_
;
732 sync_enabled_
= profile_sync_service
->GetActiveDataTypes().Has(
734 remote_service_
->SetSyncEnabled(sync_enabled_
);
735 if (!old_sync_enabled
&& sync_enabled_
)
736 RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
739 void SyncFileSystemService::RunForEachSyncRunners(
740 void(SyncProcessRunner::*method
)()) {
741 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
742 local_sync_runners_
.begin();
743 iter
!= local_sync_runners_
.end(); ++iter
)
744 ((*iter
)->*method
)();
745 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
746 remote_sync_runners_
.begin();
747 iter
!= remote_sync_runners_
.end(); ++iter
)
748 ((*iter
)->*method
)();
751 RemoteFileSyncService
* SyncFileSystemService::GetRemoteService(
752 const GURL
& origin
) {
753 return remote_service_
.get();
756 } // namespace sync_file_system