sync_file_system_service.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_dependency_manager.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_file_sync_service.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/local_file_sync_service.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_details.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webkit/fileapi/file_system_context.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "webkit/fileapi/syncable/sync_direction.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webkit/fileapi/syncable/sync_file_metadata.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webkit/fileapi/syncable/sync_status_code.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using fileapi::FileSystemURL;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURLSet;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncEventObserver::SyncServiceState RemoteStateToSyncServiceState(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoteServiceState state) {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (state) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_OK:
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SyncEventObserver::SYNC_SERVICE_RUNNING;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SyncEventObserver::SYNC_SERVICE_TEMPORARY_UNAVAILABLE;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SyncEventObserver::SYNC_SERVICE_AUTHENTICATION_REQUIRED;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_DISABLED:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SyncEventObserver::SYNC_SERVICE_DISABLED;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SyncEventObserver::SYNC_SERVICE_DISABLED;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DidHandleOriginForExtensionUnloadedEvent(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    extension_misc::UnloadedExtensionReason reason,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode code) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(chrome::NOTIFICATION_EXTENSION_UNLOADED == type);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(extension_misc::UNLOAD_REASON_DISABLE == reason ||
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         extension_misc::UNLOAD_REASON_UNINSTALL == reason);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (code != SYNC_STATUS_OK) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (reason) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case extension_misc::UNLOAD_REASON_DISABLE:
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(WARNING) << "Disabling origin for UNLOAD(DISABLE) failed: "
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     << origin.spec();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case extension_misc::UNLOAD_REASON_UNINSTALL:
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(WARNING) << "Uninstall origin for UNLOAD(UNINSTALL) failed: "
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     << origin.spec();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DidHandleOriginForExtensionEnabledEvent(
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode code) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(chrome::NOTIFICATION_EXTENSION_ENABLED == type);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (code != SYNC_STATUS_OK)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Enabling origin for ENABLED failed: " << origin.spec();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Shutdown() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_file_service_->Shutdown();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_file_service_.reset();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remote_file_service_.reset();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->RemoveObserver(this);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::~SyncFileSystemService() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::InitializeForApp(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fileapi::FileSystemContext* file_system_context,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_name,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& app_origin,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncStatusCallback& callback) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(local_file_service_);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(remote_file_service_);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(app_origin == app_origin.GetOrigin());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "InitializeForApp: " << app_origin.spec();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_file_service_->MaybeInitializeFileSystemContext(
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin, service_name, file_system_context,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidInitializeFileSystem,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::GetFileSyncStatus(
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url, const SyncFileStatusCallback& callback) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(local_file_service_);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(remote_file_service_);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It's possible to get an invalid FileEntry.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!url.is_valid()) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(callback,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_ERROR_INVALID_URL,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_STATUS_UNKNOWN));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remote_file_service_->IsConflicting(url)) {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(callback,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_STATUS_OK,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_STATUS_CONFLICTING));
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->HasPendingLocalChanges(
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), callback));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver* observer) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::RemoveSyncEventObserver(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncEventObserver* observer) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ConflictResolutionPolicy
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncFileSystemService::GetConflictResolutionPolicy() const {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return remote_file_service_->GetConflictResolutionPolicy();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncStatusCode SyncFileSystemService::SetConflictResolutionPolicy(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ConflictResolutionPolicy policy) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return remote_file_service_->SetConflictResolutionPolicy(policy);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::SyncFileSystemService(Profile* profile)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_local_changes_(0),
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_remote_changes_(0),
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      local_sync_running_(false),
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote_sync_running_(false),
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_waiting_remote_sync_enabled_(false),
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sync_enabled_(true) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Initialize(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<LocalFileSyncService> local_file_service,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<RemoteFileSyncService> remote_file_service) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(local_file_service);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(remote_file_service);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_file_service_ = local_file_service.Pass();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remote_file_service_ = remote_file_service.Pass();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->AddChangeObserver(this);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->SetLocalChangeProcessor(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote_file_service_->GetLocalChangeProcessor());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->AddServiceObserver(this);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->AddFileStatusObserver(this);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->SetRemoteChangeProcessor(local_file_service_.get());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->AddObserver(this);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 content::Source<Profile>(profile_));
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 content::Source<Profile>(profile_));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidInitializeFileSystem(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidInitializeFileSystem: "
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << app_origin.spec() << " " << status;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status != SYNC_STATUS_OK) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(status);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Local side of initialization for the app is done.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Continue on initializing the remote side.
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->RegisterOriginForTrackingChanges(
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidRegisterOrigin,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidRegisterOrigin(
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidRegisterOrigin: " << app_origin.spec() << " " << status;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(status);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sync_enabled_ = enabled;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->SetSyncEnabled(sync_enabled_);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::MaybeStartSync() {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_ || !sync_enabled_)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(local_file_service_);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(remote_file_service_);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeStartRemoteSync();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeStartLocalSync();
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::MaybeStartRemoteSync() {
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remote_file_service_->GetCurrentState() == REMOTE_SERVICE_DISABLED)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See if we cannot / should not start a new remote sync.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remote_sync_running_ || pending_remote_changes_ == 0)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we have registered a URL for waiting until sync is enabled on a
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // file (and the registerred URL seems to be still valid) it won't be
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // worth trying to start another remote sync.
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_waiting_remote_sync_enabled_)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(sync_enabled_);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Calling ProcessRemoteChange";
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_sync_running_ = true;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->ProcessRemoteChange(
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidProcessRemoteChange,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr()));
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::MaybeStartLocalSync() {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the remote service is not ready probably we should not start a
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // local sync yet.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (We should be still trying a remote sync so the state should become OK
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the remote-side attempt succeeds.)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remote_file_service_->GetCurrentState() != REMOTE_SERVICE_OK)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See if we cannot / should not start a new local sync.
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (local_sync_running_ || pending_local_changes_ == 0)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Calling ProcessLocalChange";
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_sync_running_ = true;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->ProcessLocalChange(
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidProcessLocalChange,
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr()));
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidProcessRemoteChange(
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidProcessRemoteChange: "
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " status=" << status
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " (" << SyncStatusCodeToString(status) << ")"
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " url=" << url.DebugString();
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(remote_sync_running_);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_sync_running_ = false;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote_file_service_->GetCurrentState() != REMOTE_SERVICE_DISABLED) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(url.is_valid());
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_file_service_->ClearSyncFlagForURL(url);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We seem to have no changes to work on for now.
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(kinuko): Might be better setting a timer to call MaybeStartSync.
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status == SYNC_STATUS_FILE_BUSY) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_waiting_remote_sync_enabled_ = true;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_file_service_->RegisterURLForWaitingSync(
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        url, base::Bind(&SyncFileSystemService::OnSyncEnabledForRemoteSync,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        AsWeakPtr()));
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            AsWeakPtr()));
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidProcessLocalChange(
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status, const FileSystemURL& url) {
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidProcessLocalChange:"
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " status=" << status
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " (" << SyncStatusCodeToString(status) << ")"
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " url=" << url.DebugString();
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(local_sync_running_);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_sync_running_ = false;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC) {
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We seem to have no changes to work on for now.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(url.is_valid());
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->ClearSyncFlagForURL(url);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            AsWeakPtr()));
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidGetLocalChangeStatus(
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncFileStatusCallback& callback,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_pending_local_changes) {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      status,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_pending_local_changes ?
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SYNC_FILE_STATUS_HAS_PENDING_CHANGES : SYNC_FILE_STATUS_SYNCED);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnSyncEnabledForRemoteSync() {
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_waiting_remote_sync_enabled_ = false;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeStartRemoteSync();
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnLocalChangeAvailable(int64 pending_changes) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(pending_changes, 0);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "OnLocalChangeAvailable: " << pending_changes;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_local_changes_ = pending_changes;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            AsWeakPtr()));
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnRemoteChangeQueueUpdated(int64 pending_changes) {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(pending_changes, 0);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "OnRemoteChangeQueueUpdated: " << pending_changes;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_remote_changes_ = pending_changes;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_changes > 0) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The smallest change available might have changed from the previous one.
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Reset the is_waiting_remote_sync_enabled_ flag so that we can retry.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_waiting_remote_sync_enabled_ = false;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            AsWeakPtr()));
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnRemoteServiceStateUpdated(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoteServiceState state,
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& description) {
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "OnRemoteServiceStateUpdated: " << state
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " " << description;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state == REMOTE_SERVICE_OK) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              AsWeakPtr()));
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnSyncStateUpdated(GURL(),
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         RemoteStateToSyncServiceState(state),
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         description));
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::Observe(
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationSource& source,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Delivered when an app is disabled, reloaded or restarted.
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HandleExtensionUnloaded(type, details);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Delivered when an app is enabled, reloaded or restarted.
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_ENABLED:
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HandleExtensionEnabled(type, details);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "Unknown notification.";
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::HandleExtensionUnloaded(
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::Details<const extensions::UnloadedExtensionInfo> info =
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Details<const extensions::UnloadedExtensionInfo>(details);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string extension_id = info->extension->id();
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL app_origin =
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::Extension::GetBaseURLFromExtensionId(extension_id);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (info->reason) {
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case extension_misc::UNLOAD_REASON_DISABLE:
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << app_origin;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote_file_service_->DisableOriginForTrackingChanges(
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          app_origin,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     type, info->reason, app_origin));
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      local_file_service_->SetOriginEnabled(app_origin, false);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case extension_misc::UNLOAD_REASON_UNINSTALL:
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "Handle extension notification for UNLOAD(UNINSTALL): "
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << app_origin;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote_file_service_->UninstallOrigin(
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          app_origin,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     type, info->reason, app_origin));
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      local_file_service_->SetOriginEnabled(app_origin, false);
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Nothing to do.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::HandleExtensionEnabled(
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string extension_id =
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Details<const extensions::Extension>(details)->id();
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL app_origin =
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::Extension::GetBaseURLFromExtensionId(extension_id);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Handle extension notification for ENABLED: " << app_origin;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->EnableOriginForTrackingChanges(
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DidHandleOriginForExtensionEnabledEvent, type, app_origin));
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_file_service_->SetOriginEnabled(app_origin, true);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnStateChanged() {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnFileStatusChanged(
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncFileStatus sync_status,
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncAction action_taken,
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncDirection direction) {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnFileSynced(url, sync_status, action_taken, direction));
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::UpdateSyncEnabledStatus(
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileSyncServiceBase* profile_sync_service) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_sync_service->HasSyncSetupCompleted())
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sync_enabled_ = profile_sync_service->GetPreferredDataTypes().Has(
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::APPS);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remote_file_service_->SetSyncEnabled(sync_enabled_);
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (sync_enabled_) {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(&SyncFileSystemService::MaybeStartSync,
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              AsWeakPtr()));
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sync_file_system
515