Re-enable child account detection, now behind a flag.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / sync_file_system_service.cc
blobfee6fe1500623bc65583d0a90ebeba40106eb581
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"
7 #include <string>
9 #include "base/bind.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"
38 #include "url/gurl.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 {
49 namespace {
51 const char kLocalSyncName[] = "Local sync";
52 const char kRemoteSyncName[] = "Remote sync";
54 SyncServiceState RemoteStateToSyncServiceState(
55 RemoteServiceState state) {
56 switch (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:
68 NOTREACHED();
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(
91 const GURL& origin,
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,
108 size_t* num_results,
109 const SyncFileSystemService::DumpFilesCallback& callback,
110 base::DictionaryValue* file,
111 SyncStatusCode sync_status_code,
112 SyncFileStatus sync_file_status) {
113 DCHECK(files);
114 DCHECK(num_results);
116 if (file)
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())
122 return;
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) {
132 if (!service)
133 return nullptr;
134 return service->GetLocalChangeProcessor(origin);
137 } // namespace
139 //---------------------------------------------------------------------------
140 // SyncProcessRunner's.
142 // SyncProcessRunner implementation for LocalSync.
143 class LocalSyncRunner : public SyncProcessRunner,
144 public LocalFileSyncService::Observer {
145 public:
146 LocalSyncRunner(const std::string& name,
147 SyncFileSystemService* sync_service)
148 : SyncProcessRunner(name, sync_service,
149 nullptr, /* timer_helper */
150 1 /* max_parallel_task */),
151 factory_(this) {}
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(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);
169 private:
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 {
188 public:
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),
197 factory_(this) {}
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(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 void OnRemoteServiceStateUpdated(RemoteServiceState state,
220 const std::string& description) override {
221 // Just forward to SyncFileSystemService.
222 GetSyncService()->OnRemoteServiceStateUpdated(state, description);
223 last_state_ = state;
226 private:
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(BrowserThread::CurrentlyOn(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 ProfileSyncServiceBase* profile_sync_service =
265 ProfileSyncServiceFactory::GetForProfile(profile_);
266 if (profile_sync_service)
267 profile_sync_service->RemoveObserver(this);
269 ExtensionRegistry::Get(profile_)->RemoveObserver(this);
271 profile_ = nullptr;
274 SyncFileSystemService::~SyncFileSystemService() {
275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
276 DCHECK(!profile_);
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(
331 FROM_HERE,
332 base::Bind(callback,
333 SYNC_FILE_ERROR_INVALID_URL,
334 SYNC_FILE_STATUS_UNKNOWN));
335 return;
338 local_service_->HasPendingLocalChanges(
339 url,
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_)
360 return;
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) {
372 ++*job_count;
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) {
380 ++*job_count;
381 remote_service_->PromoteDemotedChanges(promote_completion_callback);
384 promote_completion_callback.Run();
387 void SyncFileSystemService::OnPromotionCompleted(int* count) {
388 if (--*count != 0)
389 return;
390 promoting_demoted_changes_ = false;
391 CheckIfIdle();
394 void SyncFileSystemService::CheckIfIdle() {
395 if (promoting_demoted_changes_)
396 return;
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)
401 continue;
403 if (remote_sync_runners_[i]->pending_changes())
404 return;
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 continue;
412 if (local_sync_runners_[i]->pending_changes())
413 return;
416 if (idle_callback_.is_null())
417 return;
419 base::Closure callback = idle_callback_;
420 idle_callback_.Reset();
421 callback.Run();
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() {
430 return this;
433 void SyncFileSystemService::CallOnIdleForTesting(
434 const base::Closure& callback) {
435 DCHECK(idle_callback_.is_null());
436 idle_callback_ = callback;
437 CheckIfIdle();
440 SyncFileSystemService::SyncFileSystemService(Profile* profile)
441 : profile_(profile),
442 sync_enabled_(true),
443 promoting_demoted_changes_(false) {
446 void SyncFileSystemService::Initialize(
447 scoped_ptr<LocalFileSyncService> local_service,
448 scoped_ptr<RemoteFileSyncService> remote_service) {
449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
450 DCHECK(local_service);
451 DCHECK(remote_service);
452 DCHECK(profile_);
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 ProfileSyncServiceBase* profile_sync_service =
474 ProfileSyncServiceFactory::GetForProfile(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);
492 return;
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);
499 return;
502 remote_service_->RegisterOrigin(
503 app_origin,
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);
519 return;
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);
531 return;
532 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
533 callback.Run(SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE);
534 return;
535 default:
536 break;
540 callback.Run(status);
543 void SyncFileSystemService::DidInitializeFileSystemForDump(
544 const GURL& origin,
545 const DumpFilesCallback& callback,
546 SyncStatusCode status) {
547 DCHECK(!origin.is_empty());
549 if (status != SYNC_STATUS_OK) {
550 callback.Run(base::ListValue());
551 return;
554 if (!remote_service_) {
555 callback.Run(base::ListValue());
556 return;
559 remote_service_->DumpFiles(
560 origin,
561 base::Bind(
562 &SyncFileSystemService::DidDumpFiles,
563 AsWeakPtr(),
564 origin,
565 callback));
568 void SyncFileSystemService::DidDumpFiles(
569 const GURL& origin,
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());
575 return;
578 base::ListValue* files = dump_files.get();
579 base::Callback<void(base::DictionaryValue*,
580 SyncStatusCode,
581 SyncFileStatus)> completion_callback =
582 base::Bind(&DidGetFileSyncStatusForDump,
583 base::Owned(dump_files.release()),
584 base::Owned(new size_t(0)),
585 callback);
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)) {
593 NOTREACHED();
594 completion_callback.Run(
595 nullptr, SYNC_FILE_ERROR_FAILED, SYNC_FILE_STATUS_UNKNOWN);
596 continue;
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) {
607 if (!list)
608 list = make_scoped_ptr(new base::ListValue);
609 callback.Run(*list);
612 void SyncFileSystemService::DidGetExtensionStatusMap(
613 const ExtensionStatusMapCallback& callback,
614 scoped_ptr<RemoteFileSyncService::OriginStatusMap> status_map) {
615 if (!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) {
629 callback.Run(
630 status,
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(BrowserThread::CurrentlyOn(BrowserThread::UI));
639 util::Log(logging::LOG_VERBOSE, FROM_HERE,
640 "OnRemoteServiceStateChanged: %d %s", state, description.c_str());
642 FOR_EACH_OBSERVER(
643 SyncEventObserver, observers_,
644 OnSyncStateUpdated(GURL(),
645 RemoteStateToSyncServiceState(state),
646 description));
648 RunForEachSyncRunners(&SyncProcessRunner::Schedule);
651 void SyncFileSystemService::OnExtensionInstalled(
652 content::BrowserContext* browser_context,
653 const Extension* extension,
654 bool is_update) {
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)
667 return;
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
677 // restarts.
678 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE_RELOAD): "
679 << app_origin;
680 return;
683 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
684 << app_origin;
685 remote_service_->DisableOrigin(
686 app_origin,
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: "
707 << app_origin;
708 remote_service_->UninstallOrigin(
709 app_origin, flag,
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(
720 app_origin,
721 base::Bind(&DidHandleLoadEvent, app_origin));
722 local_service_->SetOriginEnabled(app_origin, true);
725 void SyncFileSystemService::OnStateChanged() {
726 ProfileSyncServiceBase* profile_sync_service =
727 ProfileSyncServiceFactory::GetForProfile(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) {
738 FOR_EACH_OBSERVER(
739 SyncEventObserver, observers_,
740 OnFileSynced(url, file_type, sync_status, action_taken, direction));
743 void SyncFileSystemService::UpdateSyncEnabledStatus(
744 ProfileSyncServiceBase* profile_sync_service) {
745 if (!profile_sync_service->HasSyncSetupCompleted())
746 return;
747 bool old_sync_enabled = sync_enabled_;
748 sync_enabled_ = profile_sync_service->GetActiveDataTypes().Has(
749 syncer::APPS);
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