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"
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 virtual 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 virtual void OnLocalChangeAvailable(int64 pending_changes
) override
{
161 DCHECK(BrowserThread::CurrentlyOn(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 virtual void StartSync(const SyncStatusCallback
& callback
) override
{
200 remote_service_
->ProcessRemoteChange(
201 base::Bind(&RemoteSyncRunner::DidProcessRemoteChange
,
202 factory_
.GetWeakPtr(), callback
));
205 virtual SyncServiceState
GetServiceState() override
{
206 return RemoteStateToSyncServiceState(last_state_
);
209 // RemoteFileSyncService::Observer overrides.
210 virtual void OnRemoteChangeQueueUpdated(int64 pending_changes
) override
{
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
213 OnChangesUpdated(pending_changes
);
215 // Kick other sync runners just in case they're not running.
216 GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
219 virtual void OnRemoteServiceStateUpdated(
220 RemoteServiceState state
,
221 const std::string
& description
) override
{
222 // Just forward to SyncFileSystemService.
223 GetSyncService()->OnRemoteServiceStateUpdated(state
, description
);
228 void DidProcessRemoteChange(
229 const SyncStatusCallback
& callback
,
230 SyncStatusCode status
,
231 const FileSystemURL
& url
) {
232 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
233 "ProcessRemoteChange finished with status=%d (%s) for url=%s",
234 status
, SyncStatusCodeToString(status
),
235 url
.DebugString().c_str());
237 if (status
== SYNC_STATUS_FILE_BUSY
) {
238 GetSyncService()->local_service_
->RegisterURLForWaitingSync(
239 url
, base::Bind(&RemoteSyncRunner::Schedule
,
240 factory_
.GetWeakPtr()));
242 callback
.Run(status
);
245 RemoteFileSyncService
* remote_service_
;
246 RemoteServiceState last_state_
;
247 base::WeakPtrFactory
<RemoteSyncRunner
> factory_
;
248 DISALLOW_COPY_AND_ASSIGN(RemoteSyncRunner
);
251 //-----------------------------------------------------------------------------
252 // SyncFileSystemService
254 void SyncFileSystemService::Shutdown() {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
257 local_sync_runners_
.clear();
258 remote_sync_runners_
.clear();
260 local_service_
->Shutdown();
261 local_service_
.reset();
263 remote_service_
.reset();
265 ProfileSyncServiceBase
* profile_sync_service
=
266 ProfileSyncServiceFactory::GetForProfile(profile_
);
267 if (profile_sync_service
)
268 profile_sync_service
->RemoveObserver(this);
270 ExtensionRegistry::Get(profile_
)->RemoveObserver(this);
275 SyncFileSystemService::~SyncFileSystemService() {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
280 void SyncFileSystemService::InitializeForApp(
281 storage::FileSystemContext
* file_system_context
,
282 const GURL
& app_origin
,
283 const SyncStatusCallback
& callback
) {
284 DCHECK(local_service_
);
285 DCHECK(remote_service_
);
286 DCHECK(app_origin
== app_origin
.GetOrigin());
288 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
289 "Initializing for App: %s", app_origin
.spec().c_str());
291 local_service_
->MaybeInitializeFileSystemContext(
292 app_origin
, file_system_context
,
293 base::Bind(&SyncFileSystemService::DidInitializeFileSystem
,
294 AsWeakPtr(), app_origin
, callback
));
297 void SyncFileSystemService::GetExtensionStatusMap(
298 const ExtensionStatusMapCallback
& callback
) {
299 remote_service_
->GetOriginStatusMap(
300 base::Bind(&SyncFileSystemService::DidGetExtensionStatusMap
,
301 AsWeakPtr(), callback
));
304 void SyncFileSystemService::DumpFiles(const GURL
& origin
,
305 const DumpFilesCallback
& callback
) {
306 DCHECK(!origin
.is_empty());
308 content::StoragePartition
* storage_partition
=
309 content::BrowserContext::GetStoragePartitionForSite(profile_
, origin
);
310 storage::FileSystemContext
* file_system_context
=
311 storage_partition
->GetFileSystemContext();
312 local_service_
->MaybeInitializeFileSystemContext(
313 origin
, file_system_context
,
314 base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump
,
315 AsWeakPtr(), origin
, callback
));
318 void SyncFileSystemService::DumpDatabase(const DumpFilesCallback
& callback
) {
319 remote_service_
->DumpDatabase(
320 base::Bind(&SyncFileSystemService::DidDumpDatabase
,
321 AsWeakPtr(), callback
));
324 void SyncFileSystemService::GetFileSyncStatus(
325 const FileSystemURL
& url
, const SyncFileStatusCallback
& callback
) {
326 DCHECK(local_service_
);
327 DCHECK(GetRemoteService(url
.origin()));
329 // It's possible to get an invalid FileEntry.
330 if (!url
.is_valid()) {
331 base::ThreadTaskRunnerHandle::Get()->PostTask(
334 SYNC_FILE_ERROR_INVALID_URL
,
335 SYNC_FILE_STATUS_UNKNOWN
));
339 local_service_
->HasPendingLocalChanges(
341 base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus
,
342 AsWeakPtr(), callback
));
345 void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver
* observer
) {
346 observers_
.AddObserver(observer
);
349 void SyncFileSystemService::RemoveSyncEventObserver(
350 SyncEventObserver
* observer
) {
351 observers_
.RemoveObserver(observer
);
354 LocalChangeProcessor
* SyncFileSystemService::GetLocalChangeProcessor(
355 const GURL
& origin
) {
356 return GetRemoteService(origin
)->GetLocalChangeProcessor();
359 void SyncFileSystemService::OnSyncIdle() {
360 if (promoting_demoted_changes_
)
362 promoting_demoted_changes_
= true;
364 int* job_count
= new int(1);
365 base::Closure promote_completion_callback
=
366 base::Bind(&SyncFileSystemService::OnPromotionCompleted
,
367 AsWeakPtr(), base::Owned(job_count
));
369 int64 remote_changes
= 0;
370 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
)
371 remote_changes
+= remote_sync_runners_
[i
]->pending_changes();
372 if (remote_changes
== 0) {
374 local_service_
->PromoteDemotedChanges(promote_completion_callback
);
377 int64 local_changes
= 0;
378 for (size_t i
= 0; i
< local_sync_runners_
.size(); ++i
)
379 local_changes
+= local_sync_runners_
[i
]->pending_changes();
380 if (local_changes
== 0) {
382 remote_service_
->PromoteDemotedChanges(promote_completion_callback
);
385 promote_completion_callback
.Run();
388 void SyncFileSystemService::OnPromotionCompleted(int* count
) {
391 promoting_demoted_changes_
= false;
395 void SyncFileSystemService::CheckIfIdle() {
396 if (promoting_demoted_changes_
)
399 for (size_t i
= 0; i
< remote_sync_runners_
.size(); ++i
) {
400 SyncServiceState service_state
= remote_sync_runners_
[i
]->GetServiceState();
401 if (service_state
!= SYNC_SERVICE_RUNNING
)
404 if (remote_sync_runners_
[i
]->pending_changes())
408 for (size_t i
= 0; i
< local_sync_runners_
.size(); ++i
) {
409 SyncServiceState service_state
= local_sync_runners_
[i
]->GetServiceState();
410 if (service_state
!= SYNC_SERVICE_RUNNING
)
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
= nullptr;
575 std::string path_string
;
576 if (!files
->GetDictionary(i
, &file
) ||
577 !file
->GetString("path", &path_string
)) {
579 completion_callback
.Run(
580 nullptr, 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 SyncFileType file_type
,
720 SyncFileStatus sync_status
,
721 SyncAction action_taken
,
722 SyncDirection direction
) {
724 SyncEventObserver
, observers_
,
725 OnFileSynced(url
, file_type
, sync_status
, action_taken
, direction
));
728 void SyncFileSystemService::UpdateSyncEnabledStatus(
729 ProfileSyncServiceBase
* profile_sync_service
) {
730 if (!profile_sync_service
->HasSyncSetupCompleted())
732 bool old_sync_enabled
= sync_enabled_
;
733 sync_enabled_
= profile_sync_service
->GetActiveDataTypes().Has(
735 remote_service_
->SetSyncEnabled(sync_enabled_
);
736 if (!old_sync_enabled
&& sync_enabled_
)
737 RunForEachSyncRunners(&SyncProcessRunner::Schedule
);
740 void SyncFileSystemService::RunForEachSyncRunners(
741 void(SyncProcessRunner::*method
)()) {
742 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
743 local_sync_runners_
.begin();
744 iter
!= local_sync_runners_
.end(); ++iter
)
745 ((*iter
)->*method
)();
746 for (ScopedVector
<SyncProcessRunner
>::iterator iter
=
747 remote_sync_runners_
.begin();
748 iter
!= remote_sync_runners_
.end(); ++iter
)
749 ((*iter
)->*method
)();
752 RemoteFileSyncService
* SyncFileSystemService::GetRemoteService(
753 const GURL
& origin
) {
754 return remote_service_
.get();
757 } // namespace sync_file_system