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_factory.h"
21 #include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
22 #include "chrome/browser/sync_file_system/logger.h"
23 #include "chrome/browser/sync_file_system/sync_direction.h"
24 #include "chrome/browser/sync_file_system/sync_event_observer.h"
25 #include "chrome/browser/sync_file_system/sync_file_metadata.h"
26 #include "chrome/browser/sync_file_system/sync_process_runner.h"
27 #include "chrome/browser/sync_file_system/sync_status_code.h"
28 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
29 #include "components/keyed_service/content/browser_context_dependency_manager.h"
30 #include "components/sync_driver/sync_service.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"
37 #include "storage/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 nullptr, /* timer_helper */
150 1 /* max_parallel_task */),
153 void StartSync(const SyncStatusCallback
& callback
) override
{
154 GetSyncService()->local_service_
->ProcessLocalChange(
155 base::Bind(&LocalSyncRunner::DidProcessLocalChange
,
156 factory_
.GetWeakPtr(), callback
));
159 // LocalFileSyncService::Observer overrides.
160 void OnLocalChangeAvailable(int64 pending_changes
) override
{
161 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
163 OnChangesUpdated(pending_changes
);
165 // Kick other sync runners just in case they're not running.
166 GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
170 void DidProcessLocalChange(
171 const SyncStatusCallback
& callback
,
172 SyncStatusCode status
,
173 const FileSystemURL
& url
) {
174 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
175 "ProcessLocalChange finished with status=%d (%s) for url=%s",
176 status
, SyncStatusCodeToString(status
),
177 url
.DebugString().c_str());
178 callback
.Run(status
);
181 base::WeakPtrFactory
<LocalSyncRunner
> factory_
;
182 DISALLOW_COPY_AND_ASSIGN(LocalSyncRunner
);
185 // SyncProcessRunner implementation for RemoteSync.
186 class RemoteSyncRunner
: public SyncProcessRunner
,
187 public RemoteFileSyncService::Observer
{
189 RemoteSyncRunner(const std::string
& name
,
190 SyncFileSystemService
* sync_service
,
191 RemoteFileSyncService
* remote_service
)
192 : SyncProcessRunner(name
, sync_service
,
193 nullptr, /* timer_helper */
194 1 /* max_parallel_task */),
195 remote_service_(remote_service
),
196 last_state_(REMOTE_SERVICE_OK
),
199 void StartSync(const SyncStatusCallback
& callback
) override
{
200 remote_service_
->ProcessRemoteChange(
201 base::Bind(&RemoteSyncRunner::DidProcessRemoteChange
,
202 factory_
.GetWeakPtr(), callback
));
205 SyncServiceState
GetServiceState() override
{
206 return RemoteStateToSyncServiceState(last_state_
);
209 // RemoteFileSyncService::Observer overrides.
210 void OnRemoteChangeQueueUpdated(int64 pending_changes
) override
{
211 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
213 OnChangesUpdated(pending_changes
);
215 // Kick other sync runners just in case they're not running.
216 GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
219 void OnRemoteServiceStateUpdated(RemoteServiceState state
,
220 const std::string
& description
) override
{
221 // Just forward to SyncFileSystemService.
222 GetSyncService()->OnRemoteServiceStateUpdated(state
, description
);
227 void DidProcessRemoteChange(
228 const SyncStatusCallback
& callback
,
229 SyncStatusCode status
,
230 const FileSystemURL
& url
) {
231 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
232 "ProcessRemoteChange finished with status=%d (%s) for url=%s",
233 status
, SyncStatusCodeToString(status
),
234 url
.DebugString().c_str());
236 if (status
== SYNC_STATUS_FILE_BUSY
) {
237 GetSyncService()->local_service_
->RegisterURLForWaitingSync(
238 url
, base::Bind(&RemoteSyncRunner::Schedule
,
239 factory_
.GetWeakPtr()));
241 callback
.Run(status
);
244 RemoteFileSyncService
* remote_service_
;
245 RemoteServiceState last_state_
;
246 base::WeakPtrFactory
<RemoteSyncRunner
> factory_
;
247 DISALLOW_COPY_AND_ASSIGN(RemoteSyncRunner
);
250 //-----------------------------------------------------------------------------
251 // SyncFileSystemService
253 void SyncFileSystemService::Shutdown() {
254 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
256 local_sync_runners_
.clear();
257 remote_sync_runners_
.clear();
259 local_service_
->Shutdown();
260 local_service_
.reset();
262 remote_service_
.reset();
264 sync_driver::SyncService
* profile_sync_service
=
265 ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_
);
266 if (profile_sync_service
)
267 profile_sync_service
->RemoveObserver(this);
269 ExtensionRegistry::Get(profile_
)->RemoveObserver(this);
274 SyncFileSystemService::~SyncFileSystemService() {
275 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
279 void SyncFileSystemService::InitializeForApp(
280 storage::FileSystemContext
* file_system_context
,
281 const GURL
& app_origin
,
282 const SyncStatusCallback
& callback
) {
283 DCHECK(local_service_
);
284 DCHECK(remote_service_
);
285 DCHECK(app_origin
== app_origin
.GetOrigin());
287 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
288 "Initializing for App: %s", app_origin
.spec().c_str());
290 local_service_
->MaybeInitializeFileSystemContext(
291 app_origin
, file_system_context
,
292 base::Bind(&SyncFileSystemService::DidInitializeFileSystem
,
293 AsWeakPtr(), app_origin
, callback
));
296 void SyncFileSystemService::GetExtensionStatusMap(
297 const ExtensionStatusMapCallback
& callback
) {
298 remote_service_
->GetOriginStatusMap(
299 base::Bind(&SyncFileSystemService::DidGetExtensionStatusMap
,
300 AsWeakPtr(), callback
));
303 void SyncFileSystemService::DumpFiles(const GURL
& origin
,
304 const DumpFilesCallback
& callback
) {
305 DCHECK(!origin
.is_empty());
307 content::StoragePartition
* storage_partition
=
308 content::BrowserContext::GetStoragePartitionForSite(profile_
, origin
);
309 storage::FileSystemContext
* file_system_context
=
310 storage_partition
->GetFileSystemContext();
311 local_service_
->MaybeInitializeFileSystemContext(
312 origin
, file_system_context
,
313 base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump
,
314 AsWeakPtr(), origin
, callback
));
317 void SyncFileSystemService::DumpDatabase(const DumpFilesCallback
& callback
) {
318 remote_service_
->DumpDatabase(
319 base::Bind(&SyncFileSystemService::DidDumpDatabase
,
320 AsWeakPtr(), callback
));
323 void SyncFileSystemService::GetFileSyncStatus(
324 const FileSystemURL
& url
, const SyncFileStatusCallback
& callback
) {
325 DCHECK(local_service_
);
326 DCHECK(remote_service_
);
328 // It's possible to get an invalid FileEntry.
329 if (!url
.is_valid()) {
330 base::ThreadTaskRunnerHandle::Get()->PostTask(
333 SYNC_FILE_ERROR_INVALID_URL
,
334 SYNC_FILE_STATUS_UNKNOWN
));
338 local_service_
->HasPendingLocalChanges(
340 base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus
,
341 AsWeakPtr(), callback
));
344 void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver
* observer
) {
345 observers_
.AddObserver(observer
);
348 void SyncFileSystemService::RemoveSyncEventObserver(
349 SyncEventObserver
* observer
) {
350 observers_
.RemoveObserver(observer
);
353 LocalChangeProcessor
* SyncFileSystemService::GetLocalChangeProcessor(
354 const GURL
& origin
) {
355 return remote_service_
->GetLocalChangeProcessor();
358 void SyncFileSystemService::OnSyncIdle() {
359 if (promoting_demoted_changes_
)
361 promoting_demoted_changes_
= true;
363 int* job_count
= new int(1);
364 base::Closure promote_completion_callback
=
365 base::Bind(&SyncFileSystemService::OnPromotionCompleted
,
366 AsWeakPtr(), base::Owned(job_count
));
368 int64 remote_changes
= 0;
369 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
)
370 remote_changes
+= remote_sync_runners_
[i
]->pending_changes();
371 if (remote_changes
== 0) {
373 local_service_
->PromoteDemotedChanges(promote_completion_callback
);
376 int64 local_changes
= 0;
377 for (size_t i
= 0; i
< local_sync_runners_
.size(); ++i
)
378 local_changes
+= local_sync_runners_
[i
]->pending_changes();
379 if (local_changes
== 0) {
381 remote_service_
->PromoteDemotedChanges(promote_completion_callback
);
384 promote_completion_callback
.Run();
387 void SyncFileSystemService::OnPromotionCompleted(int* count
) {
390 promoting_demoted_changes_
= false;
394 void SyncFileSystemService::CheckIfIdle() {
395 if (promoting_demoted_changes_
)
398 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
) {
399 SyncServiceState service_state
= remote_sync_runners_
[i
]->GetServiceState();
400 if (service_state
!= SYNC_SERVICE_RUNNING
)
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
)
412 if (local_sync_runners_
[i
]->pending_changes())
416 if (idle_callback_
.is_null())
419 base::Closure callback
= idle_callback_
;
420 idle_callback_
.Reset();
424 SyncServiceState
SyncFileSystemService::GetSyncServiceState() {
425 // For now we always query the state from the main RemoteFileSyncService.
426 return RemoteStateToSyncServiceState(remote_service_
->GetCurrentState());
429 SyncFileSystemService
* SyncFileSystemService::GetSyncService() {
433 void SyncFileSystemService::CallOnIdleForTesting(
434 const base::Closure
& callback
) {
435 DCHECK(idle_callback_
.is_null());
436 idle_callback_
= callback
;
440 SyncFileSystemService::SyncFileSystemService(Profile
* profile
)
443 promoting_demoted_changes_(false) {
446 void SyncFileSystemService::Initialize(
447 scoped_ptr
<LocalFileSyncService
> local_service
,
448 scoped_ptr
<RemoteFileSyncService
> remote_service
) {
449 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
450 DCHECK(local_service
);
451 DCHECK(remote_service
);
454 local_service_
= local_service
.Pass();
455 remote_service_
= remote_service
.Pass();
457 scoped_ptr
<LocalSyncRunner
> local_syncer(
458 new LocalSyncRunner(kLocalSyncName
, this));
459 scoped_ptr
<RemoteSyncRunner
> remote_syncer(
460 new RemoteSyncRunner(kRemoteSyncName
, this, remote_service_
.get()));
462 local_service_
->AddChangeObserver(local_syncer
.get());
463 local_service_
->SetLocalChangeProcessorCallback(
464 base::Bind(&GetLocalChangeProcessorAdapter
, AsWeakPtr()));
466 remote_service_
->AddServiceObserver(remote_syncer
.get());
467 remote_service_
->AddFileStatusObserver(this);
468 remote_service_
->SetRemoteChangeProcessor(local_service_
.get());
470 local_sync_runners_
.push_back(local_syncer
.release());
471 remote_sync_runners_
.push_back(remote_syncer
.release());
473 sync_driver::SyncService
* profile_sync_service
=
474 ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_
);
475 if (profile_sync_service
) {
476 UpdateSyncEnabledStatus(profile_sync_service
);
477 profile_sync_service
->AddObserver(this);
480 ExtensionRegistry::Get(profile_
)->AddObserver(this);
483 void SyncFileSystemService::DidInitializeFileSystem(
484 const GURL
& app_origin
,
485 const SyncStatusCallback
& callback
,
486 SyncStatusCode status
) {
487 DVLOG(1) << "DidInitializeFileSystem: "
488 << app_origin
.spec() << " " << status
;
490 if (status
!= SYNC_STATUS_OK
) {
491 callback
.Run(status
);
495 // Local side of initialization for the app is done.
496 // Continue on initializing the remote side.
497 if (!remote_service_
) {
498 callback
.Run(SYNC_STATUS_ABORT
);
502 remote_service_
->RegisterOrigin(
504 base::Bind(&SyncFileSystemService::DidRegisterOrigin
,
505 AsWeakPtr(), app_origin
, callback
));
508 void SyncFileSystemService::DidRegisterOrigin(
509 const GURL
& app_origin
,
510 const SyncStatusCallback
& callback
,
511 SyncStatusCode status
) {
512 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
513 "DidInitializeForApp (registered the origin): %s: %s",
514 app_origin
.spec().c_str(),
515 SyncStatusCodeToString(status
));
517 if (!remote_service_
) {
518 callback
.Run(SYNC_STATUS_ABORT
);
522 UMA_HISTOGRAM_ENUMERATION("SyncFileSystem.RegisterOriginResult",
523 remote_service_
->GetCurrentState(),
524 REMOTE_SERVICE_STATE_MAX
);
526 if (status
== SYNC_STATUS_FAILED
) {
527 // If we got generic error return the service status information.
528 switch (remote_service_
->GetCurrentState()) {
529 case REMOTE_SERVICE_AUTHENTICATION_REQUIRED
:
530 callback
.Run(SYNC_STATUS_AUTHENTICATION_FAILED
);
532 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
:
533 callback
.Run(SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE
);
540 callback
.Run(status
);
543 void SyncFileSystemService::DidInitializeFileSystemForDump(
545 const DumpFilesCallback
& callback
,
546 SyncStatusCode status
) {
547 DCHECK(!origin
.is_empty());
549 if (status
!= SYNC_STATUS_OK
) {
550 callback
.Run(base::ListValue());
554 if (!remote_service_
) {
555 callback
.Run(base::ListValue());
559 remote_service_
->DumpFiles(
562 &SyncFileSystemService::DidDumpFiles
,
568 void SyncFileSystemService::DidDumpFiles(
570 const DumpFilesCallback
& callback
,
571 scoped_ptr
<base::ListValue
> dump_files
) {
572 if (!dump_files
|| !dump_files
->GetSize() ||
573 !local_service_
|| !remote_service_
) {
574 callback
.Run(base::ListValue());
578 base::ListValue
* files
= dump_files
.get();
579 base::Callback
<void(base::DictionaryValue
*,
581 SyncFileStatus
)> completion_callback
=
582 base::Bind(&DidGetFileSyncStatusForDump
,
583 base::Owned(dump_files
.release()),
584 base::Owned(new size_t(0)),
587 // After all metadata loaded, sync status can be added to each entry.
588 for (size_t i
= 0; i
< files
->GetSize(); ++i
) {
589 base::DictionaryValue
* file
= nullptr;
590 std::string path_string
;
591 if (!files
->GetDictionary(i
, &file
) ||
592 !file
->GetString("path", &path_string
)) {
594 completion_callback
.Run(
595 nullptr, SYNC_FILE_ERROR_FAILED
, SYNC_FILE_STATUS_UNKNOWN
);
599 base::FilePath file_path
= base::FilePath::FromUTF8Unsafe(path_string
);
600 FileSystemURL url
= CreateSyncableFileSystemURL(origin
, file_path
);
601 GetFileSyncStatus(url
, base::Bind(completion_callback
, file
));
605 void SyncFileSystemService::DidDumpDatabase(const DumpFilesCallback
& callback
,
606 scoped_ptr
<base::ListValue
> list
) {
608 list
= make_scoped_ptr(new base::ListValue
);
612 void SyncFileSystemService::DidGetExtensionStatusMap(
613 const ExtensionStatusMapCallback
& callback
,
614 scoped_ptr
<RemoteFileSyncService::OriginStatusMap
> status_map
) {
616 status_map
= make_scoped_ptr(new RemoteFileSyncService::OriginStatusMap
);
617 callback
.Run(*status_map
);
620 void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled
) {
621 sync_enabled_
= enabled
;
622 remote_service_
->SetSyncEnabled(sync_enabled_
);
625 void SyncFileSystemService::DidGetLocalChangeStatus(
626 const SyncFileStatusCallback
& callback
,
627 SyncStatusCode status
,
628 bool has_pending_local_changes
) {
631 has_pending_local_changes
?
632 SYNC_FILE_STATUS_HAS_PENDING_CHANGES
: SYNC_FILE_STATUS_SYNCED
);
635 void SyncFileSystemService::OnRemoteServiceStateUpdated(
636 RemoteServiceState state
,
637 const std::string
& description
) {
638 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
639 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
640 "OnRemoteServiceStateChanged: %d %s", state
, description
.c_str());
643 SyncEventObserver
, observers_
,
644 OnSyncStateUpdated(GURL(),
645 RemoteStateToSyncServiceState(state
),
648 RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
651 void SyncFileSystemService::OnExtensionInstalled(
652 content::BrowserContext
* browser_context
,
653 const Extension
* extension
,
655 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
656 DVLOG(1) << "Handle extension notification for INSTALLED: " << app_origin
;
657 // NOTE: When an app is uninstalled and re-installed in a sequence,
658 // |local_service_| may still keeps |app_origin| as disabled origin.
659 local_service_
->SetOriginEnabled(app_origin
, true);
662 void SyncFileSystemService::OnExtensionUnloaded(
663 content::BrowserContext
* browser_context
,
664 const Extension
* extension
,
665 extensions::UnloadedExtensionInfo::Reason reason
) {
666 if (reason
!= extensions::UnloadedExtensionInfo::REASON_DISABLE
)
669 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
670 int disable_reasons
=
671 ExtensionPrefs::Get(profile_
)->GetDisableReasons(extension
->id());
672 if (disable_reasons
& Extension::DISABLE_RELOAD
) {
673 // Bypass disabling the origin since the app will be re-enabled soon.
674 // NOTE: If re-enabling the app fails, the app is disabled while it is
675 // handled as enabled origin in the SyncFS. This should be safe and will be
676 // recovered when the user re-enables the app manually or the sync service
678 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE_RELOAD): "
683 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
685 remote_service_
->DisableOrigin(
687 base::Bind(&DidHandleUnloadedEvent
, app_origin
));
688 local_service_
->SetOriginEnabled(app_origin
, false);
691 void SyncFileSystemService::OnExtensionUninstalled(
692 content::BrowserContext
* browser_context
,
693 const Extension
* extension
,
694 extensions::UninstallReason reason
) {
695 RemoteFileSyncService::UninstallFlag flag
=
696 RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE
;
697 // If it's loaded from an unpacked package and with key: field,
698 // the uninstall will not be sync'ed and the user might be using the
699 // same app key in other installs, so avoid purging the remote folder.
700 if (extensions::Manifest::IsUnpackedLocation(extension
->location()) &&
701 extension
->manifest()->HasKey(extensions::manifest_keys::kKey
)) {
702 flag
= RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE
;
705 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
706 DVLOG(1) << "Handle extension notification for UNINSTALLED: "
708 remote_service_
->UninstallOrigin(
710 base::Bind(&DidHandleUninstalledEvent
, app_origin
));
711 local_service_
->SetOriginEnabled(app_origin
, false);
714 void SyncFileSystemService::OnExtensionLoaded(
715 content::BrowserContext
* browser_context
,
716 const Extension
* extension
) {
717 GURL app_origin
= Extension::GetBaseURLFromExtensionId(extension
->id());
718 DVLOG(1) << "Handle extension notification for LOADED: " << app_origin
;
719 remote_service_
->EnableOrigin(
721 base::Bind(&DidHandleLoadEvent
, app_origin
));
722 local_service_
->SetOriginEnabled(app_origin
, true);
725 void SyncFileSystemService::OnStateChanged() {
726 sync_driver::SyncService
* profile_sync_service
=
727 ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_
);
728 if (profile_sync_service
)
729 UpdateSyncEnabledStatus(profile_sync_service
);
732 void SyncFileSystemService::OnFileStatusChanged(
733 const FileSystemURL
& url
,
734 SyncFileType file_type
,
735 SyncFileStatus sync_status
,
736 SyncAction action_taken
,
737 SyncDirection direction
) {
739 SyncEventObserver
, observers_
,
740 OnFileSynced(url
, file_type
, sync_status
, action_taken
, direction
));
743 void SyncFileSystemService::UpdateSyncEnabledStatus(
744 sync_driver::SyncService
* profile_sync_service
) {
745 if (!profile_sync_service
->HasSyncSetupCompleted())
747 bool old_sync_enabled
= sync_enabled_
;
748 sync_enabled_
= profile_sync_service
->GetActiveDataTypes().Has(
750 remote_service_
->SetSyncEnabled(sync_enabled_
);
751 if (!old_sync_enabled
&& sync_enabled_
)
752 RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
755 void SyncFileSystemService::RunForEachSyncRunners(
756 void(SyncProcessRunner::*method
)()) {
757 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
758 local_sync_runners_
.begin();
759 iter
!= local_sync_runners_
.end(); ++iter
)
760 ((*iter
)->*method
)();
761 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
762 remote_sync_runners_
.begin();
763 iter
!= remote_sync_runners_
.end(); ++iter
)
764 ((*iter
)->*method
)();
767 } // namespace sync_file_system