Add a minor text member to ui::MenuModel.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / sync_file_system_service.cc
blob0c733185a81b77556c4c84256930c92e4cd19cfc
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/stl_util.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
16 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/profile_sync_service.h"
19 #include "chrome/browser/sync/profile_sync_service_factory.h"
20 #include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_service.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_status_code.h"
27 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
28 #include "chrome/common/extensions/extension.h"
29 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/notification_details.h"
32 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/storage_partition.h"
34 #include "url/gurl.h"
35 #include "webkit/browser/fileapi/file_system_context.h"
37 using content::BrowserThread;
38 using fileapi::FileSystemURL;
39 using fileapi::FileSystemURLSet;
41 namespace sync_file_system {
43 namespace {
45 const int64 kRetryTimerIntervalInSeconds = 20 * 60; // 20 min.
47 SyncServiceState RemoteStateToSyncServiceState(
48 RemoteServiceState state) {
49 switch (state) {
50 case REMOTE_SERVICE_OK:
51 return SYNC_SERVICE_RUNNING;
52 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
53 return SYNC_SERVICE_TEMPORARY_UNAVAILABLE;
54 case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
55 return SYNC_SERVICE_AUTHENTICATION_REQUIRED;
56 case REMOTE_SERVICE_DISABLED:
57 return SYNC_SERVICE_DISABLED;
59 NOTREACHED() << "Unknown remote service state: " << state;
60 return SYNC_SERVICE_DISABLED;
63 void DidHandleOriginForExtensionUnloadedEvent(
64 int type,
65 const GURL& origin,
66 SyncStatusCode code) {
67 DCHECK(chrome::NOTIFICATION_EXTENSION_UNLOADED == type ||
68 chrome::NOTIFICATION_EXTENSION_UNINSTALLED == type);
69 if (code != SYNC_STATUS_OK &&
70 code != SYNC_STATUS_UNKNOWN_ORIGIN) {
71 switch (type) {
72 case chrome::NOTIFICATION_EXTENSION_UNLOADED:
73 util::Log(logging::LOG_WARNING,
74 FROM_HERE,
75 "Disabling origin for UNLOADED(DISABLE) failed: %s",
76 origin.spec().c_str());
77 break;
78 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
79 util::Log(logging::LOG_WARNING,
80 FROM_HERE,
81 "Uninstall origin for UNINSTALLED failed: %s",
82 origin.spec().c_str());
83 break;
84 default:
85 break;
90 void DidHandleOriginForExtensionEnabledEvent(
91 int type,
92 const GURL& origin,
93 SyncStatusCode code) {
94 DCHECK(chrome::NOTIFICATION_EXTENSION_ENABLED == type);
95 if (code != SYNC_STATUS_OK)
96 util::Log(logging::LOG_WARNING,
97 FROM_HERE,
98 "Enabling origin for ENABLED failed: %s",
99 origin.spec().c_str());
102 std::string SyncFileStatusToString(SyncFileStatus sync_file_status) {
103 return extensions::api::sync_file_system::ToString(
104 extensions::SyncFileStatusToExtensionEnum(sync_file_status));
107 // Gets called repeatedly until every SyncFileStatus has been mapped.
108 void DidGetFileSyncStatusForDump(
109 base::ListValue* files,
110 size_t* num_results,
111 const SyncFileSystemService::DumpFilesCallback& callback,
112 base::DictionaryValue* file,
113 SyncStatusCode sync_status_code,
114 SyncFileStatus sync_file_status) {
115 DCHECK(files);
116 DCHECK(num_results);
118 if (file)
119 file->SetString("status", SyncFileStatusToString(sync_file_status));
121 // Once all results have been received, run the callback to signal end.
122 DCHECK_LE(*num_results, files->GetSize());
123 if (++*num_results < files->GetSize())
124 return;
126 callback.Run(files);
129 } // namespace
131 void SyncFileSystemService::Shutdown() {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
134 local_file_service_->Shutdown();
135 local_file_service_.reset();
137 remote_file_service_.reset();
139 ProfileSyncServiceBase* profile_sync_service =
140 ProfileSyncServiceFactory::GetForProfile(profile_);
141 if (profile_sync_service)
142 profile_sync_service->RemoveObserver(this);
144 profile_ = NULL;
147 SyncFileSystemService::~SyncFileSystemService() {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
149 DCHECK(!profile_);
152 void SyncFileSystemService::InitializeForApp(
153 fileapi::FileSystemContext* file_system_context,
154 const GURL& app_origin,
155 const SyncStatusCallback& callback) {
156 DCHECK(local_file_service_);
157 DCHECK(remote_file_service_);
158 DCHECK(app_origin == app_origin.GetOrigin());
160 util::Log(logging::LOG_VERBOSE, FROM_HERE,
161 "Initializing for App: %s", app_origin.spec().c_str());
163 local_file_service_->MaybeInitializeFileSystemContext(
164 app_origin, file_system_context,
165 base::Bind(&SyncFileSystemService::DidInitializeFileSystem,
166 AsWeakPtr(), app_origin, callback));
169 SyncServiceState SyncFileSystemService::GetSyncServiceState() {
170 return RemoteStateToSyncServiceState(remote_file_service_->GetCurrentState());
173 void SyncFileSystemService::GetExtensionStatusMap(
174 std::map<GURL, std::string>* status_map) {
175 DCHECK(status_map);
176 remote_file_service_->GetOriginStatusMap(status_map);
179 void SyncFileSystemService::DumpFiles(const GURL& origin,
180 const DumpFilesCallback& callback) {
181 DCHECK(!origin.is_empty());
183 content::StoragePartition* storage_partition =
184 content::BrowserContext::GetStoragePartitionForSite(profile_, origin);
185 fileapi::FileSystemContext* file_system_context =
186 storage_partition->GetFileSystemContext();
187 local_file_service_->MaybeInitializeFileSystemContext(
188 origin, file_system_context,
189 base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump,
190 AsWeakPtr(), origin, callback));
193 void SyncFileSystemService::GetFileSyncStatus(
194 const FileSystemURL& url, const SyncFileStatusCallback& callback) {
195 DCHECK(local_file_service_);
196 DCHECK(remote_file_service_);
198 // It's possible to get an invalid FileEntry.
199 if (!url.is_valid()) {
200 base::MessageLoopProxy::current()->PostTask(
201 FROM_HERE,
202 base::Bind(callback,
203 SYNC_FILE_ERROR_INVALID_URL,
204 SYNC_FILE_STATUS_UNKNOWN));
205 return;
208 if (remote_file_service_->IsConflicting(url)) {
209 base::MessageLoopProxy::current()->PostTask(
210 FROM_HERE,
211 base::Bind(callback,
212 SYNC_STATUS_OK,
213 SYNC_FILE_STATUS_CONFLICTING));
214 return;
217 local_file_service_->HasPendingLocalChanges(
218 url,
219 base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus,
220 AsWeakPtr(), callback));
223 void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver* observer) {
224 observers_.AddObserver(observer);
227 void SyncFileSystemService::RemoveSyncEventObserver(
228 SyncEventObserver* observer) {
229 observers_.RemoveObserver(observer);
232 ConflictResolutionPolicy
233 SyncFileSystemService::GetConflictResolutionPolicy() const {
234 return remote_file_service_->GetConflictResolutionPolicy();
237 SyncStatusCode SyncFileSystemService::SetConflictResolutionPolicy(
238 ConflictResolutionPolicy policy) {
239 return remote_file_service_->SetConflictResolutionPolicy(policy);
242 SyncFileSystemService::SyncFileSystemService(Profile* profile)
243 : profile_(profile),
244 pending_local_changes_(0),
245 pending_remote_changes_(0),
246 local_sync_running_(false),
247 remote_sync_running_(false),
248 is_waiting_remote_sync_enabled_(false),
249 sync_enabled_(true) {
252 void SyncFileSystemService::Initialize(
253 scoped_ptr<LocalFileSyncService> local_file_service,
254 scoped_ptr<RemoteFileSyncService> remote_file_service) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256 DCHECK(local_file_service);
257 DCHECK(remote_file_service);
258 DCHECK(profile_);
260 local_file_service_ = local_file_service.Pass();
261 remote_file_service_ = remote_file_service.Pass();
263 local_file_service_->AddChangeObserver(this);
264 local_file_service_->SetLocalChangeProcessor(
265 remote_file_service_->GetLocalChangeProcessor());
267 remote_file_service_->AddServiceObserver(this);
268 remote_file_service_->AddFileStatusObserver(this);
269 remote_file_service_->SetRemoteChangeProcessor(local_file_service_.get());
271 ProfileSyncServiceBase* profile_sync_service =
272 ProfileSyncServiceFactory::GetForProfile(profile_);
273 if (profile_sync_service) {
274 UpdateSyncEnabledStatus(profile_sync_service);
275 profile_sync_service->AddObserver(this);
278 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
279 content::Source<Profile>(profile_));
280 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
281 content::Source<Profile>(profile_));
282 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
283 content::Source<Profile>(profile_));
284 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
285 content::Source<Profile>(profile_));
288 void SyncFileSystemService::DidInitializeFileSystem(
289 const GURL& app_origin,
290 const SyncStatusCallback& callback,
291 SyncStatusCode status) {
292 DVLOG(1) << "DidInitializeFileSystem: "
293 << app_origin.spec() << " " << status;
295 if (status != SYNC_STATUS_OK) {
296 callback.Run(status);
297 return;
300 // Local side of initialization for the app is done.
301 // Continue on initializing the remote side.
302 remote_file_service_->RegisterOriginForTrackingChanges(
303 app_origin,
304 base::Bind(&SyncFileSystemService::DidRegisterOrigin,
305 AsWeakPtr(), app_origin, callback));
308 void SyncFileSystemService::DidRegisterOrigin(
309 const GURL& app_origin,
310 const SyncStatusCallback& callback,
311 SyncStatusCode status) {
312 DVLOG(1) << "DidRegisterOrigin: " << app_origin.spec() << " " << status;
314 callback.Run(status);
317 void SyncFileSystemService::DidInitializeFileSystemForDump(
318 const GURL& origin,
319 const DumpFilesCallback& callback,
320 SyncStatusCode status) {
321 DCHECK(!origin.is_empty());
323 if (status != SYNC_STATUS_OK) {
324 base::ListValue empty_result;
325 callback.Run(&empty_result);
326 return;
329 base::ListValue* files = remote_file_service_->DumpFiles(origin).release();
330 if (!files->GetSize()) {
331 callback.Run(files);
332 return;
335 base::Callback<void(base::DictionaryValue* file,
336 SyncStatusCode sync_status,
337 SyncFileStatus sync_file_status)> completion_callback =
338 base::Bind(&DidGetFileSyncStatusForDump, base::Owned(files),
339 base::Owned(new size_t(0)), callback);
341 // After all metadata loaded, sync status can be added to each entry.
342 for (size_t i = 0; i < files->GetSize(); ++i) {
343 base::DictionaryValue* file = NULL;
344 std::string path_string;
345 if (!files->GetDictionary(i, &file) ||
346 !file->GetString("path", &path_string)) {
347 NOTREACHED();
348 completion_callback.Run(
349 NULL, SYNC_FILE_ERROR_FAILED, SYNC_FILE_STATUS_UNKNOWN);
350 continue;
353 base::FilePath file_path = base::FilePath::FromUTF8Unsafe(path_string);
354 FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path);
355 GetFileSyncStatus(url, base::Bind(completion_callback, file));
359 void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled) {
360 sync_enabled_ = enabled;
361 remote_file_service_->SetSyncEnabled(sync_enabled_);
364 void SyncFileSystemService::MaybeStartSync() {
365 if (!profile_ || !sync_enabled_)
366 return;
368 if (pending_local_changes_ + pending_remote_changes_ == 0)
369 return;
371 DVLOG(2) << "MaybeStartSync() called (remote service state:"
372 << remote_file_service_->GetCurrentState() << ")";
373 switch (remote_file_service_->GetCurrentState()) {
374 case REMOTE_SERVICE_OK:
375 break;
377 case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
378 if (sync_retry_timer_.IsRunning())
379 return;
380 sync_retry_timer_.Start(
381 FROM_HERE,
382 base::TimeDelta::FromSeconds(kRetryTimerIntervalInSeconds),
383 this, &SyncFileSystemService::MaybeStartSync);
384 break;
386 case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
387 case REMOTE_SERVICE_DISABLED:
388 // No point to run sync.
389 return;
392 StartRemoteSync();
393 StartLocalSync();
396 void SyncFileSystemService::StartRemoteSync() {
397 // See if we cannot / should not start a new remote sync.
398 if (remote_sync_running_ || pending_remote_changes_ == 0)
399 return;
400 // If we have registered a URL for waiting until sync is enabled on a
401 // file (and the registerred URL seems to be still valid) it won't be
402 // worth trying to start another remote sync.
403 if (is_waiting_remote_sync_enabled_)
404 return;
405 DCHECK(sync_enabled_);
407 util::Log(logging::LOG_VERBOSE, FROM_HERE,
408 "Calling ProcessRemoteChange for RemoteSync");
409 remote_sync_running_ = true;
410 remote_file_service_->ProcessRemoteChange(
411 base::Bind(&SyncFileSystemService::DidProcessRemoteChange,
412 AsWeakPtr()));
415 void SyncFileSystemService::StartLocalSync() {
416 // See if we cannot / should not start a new local sync.
417 if (local_sync_running_ || pending_local_changes_ == 0)
418 return;
419 DCHECK(sync_enabled_);
421 util::Log(logging::LOG_VERBOSE, FROM_HERE,
422 "Calling ProcessLocalChange for LocalSync");
423 local_sync_running_ = true;
424 local_file_service_->ProcessLocalChange(
425 base::Bind(&SyncFileSystemService::DidProcessLocalChange,
426 AsWeakPtr()));
429 void SyncFileSystemService::DidProcessRemoteChange(
430 SyncStatusCode status,
431 const FileSystemURL& url) {
432 util::Log(logging::LOG_VERBOSE, FROM_HERE,
433 "ProcessRemoteChange finished with status=%d (%s) for url=%s",
434 status, SyncStatusCodeToString(status), url.DebugString().c_str());
435 DCHECK(remote_sync_running_);
436 remote_sync_running_ = false;
438 if (status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
439 remote_file_service_->GetCurrentState() != REMOTE_SERVICE_DISABLED) {
440 DCHECK(url.is_valid());
441 local_file_service_->ClearSyncFlagForURL(url);
444 if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC) {
445 // We seem to have no changes to work on for now.
446 // TODO(kinuko): Might be better setting a timer to call MaybeStartSync.
447 return;
449 if (status == SYNC_STATUS_FILE_BUSY) {
450 is_waiting_remote_sync_enabled_ = true;
451 local_file_service_->RegisterURLForWaitingSync(
452 url, base::Bind(&SyncFileSystemService::OnSyncEnabledForRemoteSync,
453 AsWeakPtr()));
454 return;
457 base::MessageLoopProxy::current()->PostTask(
458 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
459 AsWeakPtr()));
462 void SyncFileSystemService::DidProcessLocalChange(
463 SyncStatusCode status, const FileSystemURL& url) {
464 util::Log(logging::LOG_VERBOSE, FROM_HERE,
465 "ProcessLocalChange finished with status=%d (%s) for url=%s",
466 status, SyncStatusCodeToString(status), url.DebugString().c_str());
467 DCHECK(local_sync_running_);
468 local_sync_running_ = false;
470 if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC) {
471 // We seem to have no changes to work on for now.
472 return;
475 DCHECK(url.is_valid());
476 local_file_service_->ClearSyncFlagForURL(url);
478 base::MessageLoopProxy::current()->PostTask(
479 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
480 AsWeakPtr()));
483 void SyncFileSystemService::DidGetLocalChangeStatus(
484 const SyncFileStatusCallback& callback,
485 SyncStatusCode status,
486 bool has_pending_local_changes) {
487 callback.Run(
488 status,
489 has_pending_local_changes ?
490 SYNC_FILE_STATUS_HAS_PENDING_CHANGES : SYNC_FILE_STATUS_SYNCED);
493 void SyncFileSystemService::OnSyncEnabledForRemoteSync() {
494 is_waiting_remote_sync_enabled_ = false;
495 MaybeStartSync();
498 void SyncFileSystemService::OnLocalChangeAvailable(int64 pending_changes) {
499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
500 DCHECK_GE(pending_changes, 0);
501 if (pending_local_changes_ != pending_changes) {
502 util::Log(logging::LOG_VERBOSE, FROM_HERE,
503 "OnLocalChangeAvailable: %" PRId64, pending_changes);
505 pending_local_changes_ = pending_changes;
506 if (pending_changes == 0)
507 return;
509 base::MessageLoopProxy::current()->PostTask(
510 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
511 AsWeakPtr()));
514 void SyncFileSystemService::OnRemoteChangeQueueUpdated(int64 pending_changes) {
515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
516 DCHECK_GE(pending_changes, 0);
518 if (pending_remote_changes_ != pending_changes) {
519 util::Log(logging::LOG_VERBOSE, FROM_HERE,
520 "OnRemoteChangeAvailable: %" PRId64, pending_changes);
522 pending_remote_changes_ = pending_changes;
523 if (pending_changes == 0)
524 return;
526 // The smallest change available might have changed from the previous one.
527 // Reset the is_waiting_remote_sync_enabled_ flag so that we can retry.
528 is_waiting_remote_sync_enabled_ = false;
530 base::MessageLoopProxy::current()->PostTask(
531 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
532 AsWeakPtr()));
535 void SyncFileSystemService::OnRemoteServiceStateUpdated(
536 RemoteServiceState state,
537 const std::string& description) {
538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
539 util::Log(logging::LOG_INFO, FROM_HERE,
540 "OnRemoteServiceStateChanged: %d %s", state, description.c_str());
542 if (state == REMOTE_SERVICE_OK) {
543 base::MessageLoopProxy::current()->PostTask(
544 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
545 AsWeakPtr()));
548 FOR_EACH_OBSERVER(
549 SyncEventObserver, observers_,
550 OnSyncStateUpdated(GURL(),
551 RemoteStateToSyncServiceState(state),
552 description));
555 void SyncFileSystemService::Observe(
556 int type,
557 const content::NotificationSource& source,
558 const content::NotificationDetails& details) {
559 // Event notification sequence.
561 // (User action) (Notification type)
562 // Install: INSTALLED.
563 // Update: INSTALLED.
564 // Uninstall: UNINSTALLED.
565 // Launch, Close: No notification.
566 // Enable: ENABLED.
567 // Disable: UNLOADED(DISABLE).
568 // Reload, Restart: UNLOADED(DISABLE) -> INSTALLED -> ENABLED.
570 switch (type) {
571 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
572 HandleExtensionInstalled(details);
573 break;
574 case chrome::NOTIFICATION_EXTENSION_UNLOADED:
575 HandleExtensionUnloaded(type, details);
576 break;
577 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
578 HandleExtensionUninstalled(type, details);
579 break;
580 case chrome::NOTIFICATION_EXTENSION_ENABLED:
581 HandleExtensionEnabled(type, details);
582 break;
583 default:
584 NOTREACHED() << "Unknown notification.";
585 break;
589 void SyncFileSystemService::HandleExtensionInstalled(
590 const content::NotificationDetails& details) {
591 const extensions::Extension* extension =
592 content::Details<const extensions::InstalledExtensionInfo>(details)->
593 extension;
594 GURL app_origin =
595 extensions::Extension::GetBaseURLFromExtensionId(extension->id());
596 DVLOG(1) << "Handle extension notification for INSTALLED: " << app_origin;
597 // NOTE: When an app is uninstalled and re-installed in a sequence,
598 // |local_file_service_| may still keeps |app_origin| as disabled origin.
599 local_file_service_->SetOriginEnabled(app_origin, true);
602 void SyncFileSystemService::HandleExtensionUnloaded(
603 int type,
604 const content::NotificationDetails& details) {
605 content::Details<const extensions::UnloadedExtensionInfo> info(details);
606 std::string extension_id = info->extension->id();
607 GURL app_origin =
608 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
609 if (info->reason != extension_misc::UNLOAD_REASON_DISABLE)
610 return;
611 DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
612 << app_origin;
613 remote_file_service_->DisableOriginForTrackingChanges(
614 app_origin,
615 base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
616 type, app_origin));
617 local_file_service_->SetOriginEnabled(app_origin, false);
620 void SyncFileSystemService::HandleExtensionUninstalled(
621 int type,
622 const content::NotificationDetails& details) {
623 std::string extension_id =
624 content::Details<const extensions::Extension>(details)->id();
625 GURL app_origin =
626 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
627 DVLOG(1) << "Handle extension notification for UNINSTALLED: "
628 << app_origin;
629 remote_file_service_->UninstallOrigin(
630 app_origin,
631 base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
632 type, app_origin));
633 local_file_service_->SetOriginEnabled(app_origin, false);
636 void SyncFileSystemService::HandleExtensionEnabled(
637 int type,
638 const content::NotificationDetails& details) {
639 std::string extension_id =
640 content::Details<const extensions::Extension>(details)->id();
641 GURL app_origin =
642 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
643 DVLOG(1) << "Handle extension notification for ENABLED: " << app_origin;
644 remote_file_service_->EnableOriginForTrackingChanges(
645 app_origin,
646 base::Bind(&DidHandleOriginForExtensionEnabledEvent, type, app_origin));
647 local_file_service_->SetOriginEnabled(app_origin, true);
650 void SyncFileSystemService::OnStateChanged() {
651 ProfileSyncServiceBase* profile_sync_service =
652 ProfileSyncServiceFactory::GetForProfile(profile_);
653 if (profile_sync_service)
654 UpdateSyncEnabledStatus(profile_sync_service);
657 void SyncFileSystemService::OnFileStatusChanged(
658 const FileSystemURL& url,
659 SyncFileStatus sync_status,
660 SyncAction action_taken,
661 SyncDirection direction) {
662 FOR_EACH_OBSERVER(
663 SyncEventObserver, observers_,
664 OnFileSynced(url, sync_status, action_taken, direction));
667 void SyncFileSystemService::UpdateSyncEnabledStatus(
668 ProfileSyncServiceBase* profile_sync_service) {
669 if (!profile_sync_service->HasSyncSetupCompleted())
670 return;
671 sync_enabled_ = profile_sync_service->GetActiveDataTypes().Has(
672 syncer::APPS);
673 remote_file_service_->SetSyncEnabled(sync_enabled_);
674 if (sync_enabled_) {
675 base::MessageLoopProxy::current()->PostTask(
676 FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
677 AsWeakPtr()));
681 } // namespace sync_file_system