blob: 4f57fb51b14d16f75779a2c3842941eb58969757 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_
#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_
#include <deque>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/drive/drive_notification_observer.h"
#include "chrome/browser/sync_file_system/conflict_resolution_resolver.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/api_util_interface.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/local_sync_operation_resolver.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/origin_operation_queue.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/remote_change_handler.h"
#include "chrome/browser/sync_file_system/file_change.h"
#include "chrome/browser/sync_file_system/local_change_processor.h"
#include "chrome/browser/sync_file_system/remote_file_sync_service.h"
#include "chrome/browser/sync_file_system/sync_action.h"
#include "chrome/browser/sync_file_system/sync_callbacks.h"
#include "chrome/browser/sync_file_system/sync_direction.h"
#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
#include "chrome/browser/sync_file_system/sync_status_code.h"
#include "chrome/browser/sync_file_system/sync_task_manager.h"
class ExtensionService;
namespace google_apis {
class ResourceList;
}
namespace tracked_objects {
class Location;
}
namespace sync_file_system {
namespace drive_backend {
class LocalSyncDelegate;
class RemoteSyncDelegate;
}
class SyncTaskManager;
// Maintains remote file changes.
// Owned by SyncFileSystemService (which is a per-profile object).
class DriveFileSyncService : public RemoteFileSyncService,
public LocalChangeProcessor,
public drive_backend::APIUtilObserver,
public SyncTaskManager::Client,
public base::NonThreadSafe,
public base::SupportsWeakPtr<DriveFileSyncService>,
public drive::DriveNotificationObserver {
public:
typedef base::Callback<void(const SyncStatusCallback& callback)> Task;
static ConflictResolutionPolicy kDefaultPolicy;
virtual ~DriveFileSyncService();
// Creates DriveFileSyncService.
static scoped_ptr<DriveFileSyncService> Create(Profile* profile);
// Creates DriveFileSyncService instance for testing.
// |metadata_store| must be initialized beforehand.
static scoped_ptr<DriveFileSyncService> CreateForTesting(
Profile* profile,
const base::FilePath& base_dir,
scoped_ptr<drive_backend::APIUtilInterface> api_util,
scoped_ptr<DriveMetadataStore> metadata_store);
// Destroys |sync_service| and passes the ownership of |sync_client| to caller
// for testing.
static scoped_ptr<drive_backend::APIUtilInterface>
DestroyAndPassAPIUtilForTesting(
scoped_ptr<DriveFileSyncService> sync_service);
// RemoteFileSyncService overrides.
virtual void AddServiceObserver(Observer* observer) OVERRIDE;
virtual void AddFileStatusObserver(FileStatusObserver* observer) OVERRIDE;
virtual void RegisterOrigin(const GURL& origin,
const SyncStatusCallback& callback) OVERRIDE;
virtual void EnableOrigin(const GURL& origin,
const SyncStatusCallback& callback) OVERRIDE;
virtual void DisableOrigin(const GURL& origin,
const SyncStatusCallback& callback) OVERRIDE;
virtual void UninstallOrigin(const GURL& origin,
const SyncStatusCallback& callback) OVERRIDE;
virtual void ProcessRemoteChange(const SyncFileCallback& callback) OVERRIDE;
virtual void SetRemoteChangeProcessor(
RemoteChangeProcessor* processor) OVERRIDE;
virtual LocalChangeProcessor* GetLocalChangeProcessor() OVERRIDE;
virtual bool IsConflicting(const fileapi::FileSystemURL& url) OVERRIDE;
virtual RemoteServiceState GetCurrentState() const OVERRIDE;
virtual void GetOriginStatusMap(OriginStatusMap* status_map) OVERRIDE;
virtual scoped_ptr<base::ListValue> DumpFiles(const GURL& origin) OVERRIDE;
virtual void SetSyncEnabled(bool enabled) OVERRIDE;
virtual SyncStatusCode SetConflictResolutionPolicy(
ConflictResolutionPolicy policy) OVERRIDE;
virtual ConflictResolutionPolicy GetConflictResolutionPolicy() const OVERRIDE;
virtual void GetRemoteVersions(
const fileapi::FileSystemURL& url,
const RemoteVersionsCallback& callback) OVERRIDE;
virtual void DownloadRemoteVersion(
const fileapi::FileSystemURL& url,
const std::string& version_id,
const DownloadVersionCallback& callback) OVERRIDE;
// LocalChangeProcessor overrides.
virtual void ApplyLocalChange(
const FileChange& change,
const base::FilePath& local_file_path,
const SyncFileMetadata& local_file_metadata,
const fileapi::FileSystemURL& url,
const SyncStatusCallback& callback) OVERRIDE;
// DriveFileSyncClientObserver overrides.
virtual void OnAuthenticated() OVERRIDE;
virtual void OnNetworkConnected() OVERRIDE;
// drive::DriveNotificationObserver implementation.
virtual void OnNotificationReceived() OVERRIDE;
virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE;
// SyncTaskManager::Client overrides.
virtual void MaybeScheduleNextTask() OVERRIDE;
virtual void NotifyLastOperationStatus(SyncStatusCode sync_status) OVERRIDE;
static std::string PathToTitle(const base::FilePath& path);
static base::FilePath TitleToPath(const std::string& title);
static DriveMetadata::ResourceType SyncFileTypeToDriveMetadataResourceType(
SyncFileType file_type);
static SyncFileType DriveMetadataResourceTypeToSyncFileType(
DriveMetadata::ResourceType resource_type);
private:
friend class SyncTaskManager;
friend class drive_backend::LocalSyncDelegate;
friend class drive_backend::RemoteSyncDelegate;
friend class DriveFileSyncServiceFakeTest;
friend class DriveFileSyncServiceSyncTest;
friend class DriveFileSyncServiceTest;
struct ApplyLocalChangeParam;
struct ProcessRemoteChangeParam;
typedef base::Callback<
void(SyncStatusCode status,
const std::string& resource_id)> ResourceIdCallback;
explicit DriveFileSyncService(Profile* profile);
void Initialize(scoped_ptr<SyncTaskManager> task_manager,
const SyncStatusCallback& callback);
void InitializeForTesting(
scoped_ptr<SyncTaskManager> task_manager,
const base::FilePath& base_dir,
scoped_ptr<drive_backend::APIUtilInterface> sync_client,
scoped_ptr<DriveMetadataStore> metadata_store,
const SyncStatusCallback& callback);
void DidInitializeMetadataStore(const SyncStatusCallback& callback,
SyncStatusCode status,
bool created);
void DidGetDriveRootResourceId(const SyncStatusCallback& callback,
google_apis::GDataErrorCode error,
const std::string& root_resource_id);
void UpdateServiceStateFromLastOperationStatus(
SyncStatusCode sync_status,
google_apis::GDataErrorCode gdata_error);
// Updates the service state. Also this may notify observers if the
// service state has been changed from the original value.
void UpdateServiceState(RemoteServiceState state,
const std::string& description);
void DoRegisterOrigin(
const GURL& origin,
const SyncStatusCallback& callback);
void DoEnableOrigin(
const GURL& origin,
const SyncStatusCallback& callback);
void DoDisableOrigin(
const GURL& origin,
const SyncStatusCallback& callback);
void DoUninstallOrigin(
const GURL& origin,
const SyncStatusCallback& callback);
void DoProcessRemoteChange(
const SyncFileCallback& sync_callback,
const SyncStatusCallback& completion_callback);
void DoApplyLocalChange(
const FileChange& change,
const base::FilePath& local_file_path,
const SyncFileMetadata& local_file_metadata,
const fileapi::FileSystemURL& url,
const SyncStatusCallback& callback);
void DoGetRemoteVersions(
const fileapi::FileSystemURL& url,
const RemoteVersionsCallback& callback,
const SyncStatusCallback& completion_callback);
void DidGetEntryForRemoteVersions(
const RemoteVersionsCallback& callback,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::ResourceEntry> entry);
void DoDownloadRemoteVersion(
const fileapi::FileSystemURL& url,
const std::string& version_id,
const DownloadVersionCallback& callback,
const SyncStatusCallback& completion_callback);
void DidDownloadVersion(
const DownloadVersionCallback& download_callback,
google_apis::GDataErrorCode error,
const std::string& file_md5,
int64 file_size,
const base::Time& last_updated,
scoped_ptr<webkit_blob::ScopedFile> downloaded);
void UpdateRegisteredOrigins();
void StartBatchSync(const SyncStatusCallback& callback);
void GetDriveDirectoryForOrigin(const GURL& origin,
const SyncStatusCallback& callback,
const std::string& sync_root_resource_id);
void DidGetDriveDirectoryForOrigin(const GURL& origin,
const SyncStatusCallback& callback,
SyncStatusCode status,
const std::string& resource_id);
void DidUninstallOrigin(const GURL& origin,
const SyncStatusCallback& callback,
google_apis::GDataErrorCode error);
void DidGetLargestChangeStampForBatchSync(
const SyncStatusCallback& callback,
const GURL& origin,
const std::string& resource_id,
google_apis::GDataErrorCode error,
int64 largest_changestamp);
void DidGetDirectoryContentForBatchSync(
const SyncStatusCallback& callback,
const GURL& origin,
const std::string& resource_id,
int64 largest_changestamp,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::ResourceList> feed);
void DidProcessRemoteChange(const SyncFileCallback& sync_callback,
const SyncStatusCallback& completion_callback,
SyncStatusCode status);
void DidApplyLocalChange(const SyncStatusCallback& callback,
SyncStatusCode status);
// Returns true if |pending_changes_| was updated.
bool AppendRemoteChange(
const GURL& origin,
const google_apis::ResourceEntry& entry,
int64 changestamp);
bool AppendFetchChange(
const GURL& origin,
const base::FilePath& path,
const std::string& resource_id,
SyncFileType file_type);
bool AppendRemoteChangeInternal(
const GURL& origin,
const base::FilePath& path,
bool is_deleted,
const std::string& resource_id,
int64 changestamp,
const std::string& remote_file_md5,
const base::Time& updated_time,
SyncFileType file_type);
void RemoveRemoteChange(const fileapi::FileSystemURL& url);
void MaybeMarkAsIncrementalSyncOrigin(const GURL& origin);
// TODO(kinuko,tzik): Move this out of DriveFileSyncService.
void MarkConflict(
const fileapi::FileSystemURL& url,
DriveMetadata* drive_metadata,
const SyncStatusCallback& callback);
void NotifyConflict(
const fileapi::FileSystemURL& url,
const SyncStatusCallback& callback,
SyncStatusCode status);
// A wrapper implementation to GDataErrorCodeToSyncStatusCode which returns
// authentication error if the user is not signed in.
SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper(
google_apis::GDataErrorCode error);
base::FilePath temporary_file_dir_;
// May start batch sync or incremental sync.
// This posts either one of following tasks:
// - StartBatchSyncForOrigin() if it has any pending batch sync origins, or
// - FetchChangesForIncrementalSync() otherwise.
//
// These two methods are called only from this method.
void MaybeStartFetchChanges();
void FetchChangesForIncrementalSync(const SyncStatusCallback& callback);
void DidFetchChangesForIncrementalSync(
const SyncStatusCallback& callback,
bool has_new_changes,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::ResourceList> changes);
bool GetOriginForEntry(const google_apis::ResourceEntry& entry, GURL* origin);
void NotifyObserversFileStatusChanged(const fileapi::FileSystemURL& url,
SyncFileStatus sync_status,
SyncAction action_taken,
SyncDirection direction);
void HandleSyncRootDirectoryChange(const google_apis::ResourceEntry& entry);
void HandleOriginRootDirectoryChange(const google_apis::ResourceEntry& entry);
void EnsureSyncRootDirectory(const ResourceIdCallback& callback);
void DidEnsureSyncRoot(const ResourceIdCallback& callback,
google_apis::GDataErrorCode error,
const std::string& sync_root_resource_id);
void EnsureOriginRootDirectory(const GURL& origin,
const ResourceIdCallback& callback);
void DidEnsureSyncRootForOriginRoot(const GURL& origin,
const ResourceIdCallback& callback,
SyncStatusCode status,
const std::string& sync_root_resource_id);
void DidEnsureOriginRoot(const GURL& origin,
const ResourceIdCallback& callback,
google_apis::GDataErrorCode error,
const std::string& resource_id);
// This function returns Resouce ID for the sync root directory if available.
// Returns an empty string 1) when the resource ID has not been initialized
// yet, and 2) after the service has detected the remote sync root folder was
// removed.
std::string sync_root_resource_id();
scoped_ptr<DriveMetadataStore> metadata_store_;
scoped_ptr<drive_backend::APIUtilInterface> api_util_;
Profile* profile_;
scoped_ptr<SyncTaskManager> task_manager_;
scoped_ptr<drive_backend::LocalSyncDelegate> running_local_sync_task_;
scoped_ptr<drive_backend::RemoteSyncDelegate> running_remote_sync_task_;
// The current remote service state. This does NOT reflect the
// sync_enabled_ flag, while GetCurrentState() DOES reflect the flag
// value (i.e. it returns REMOTE_SERVICE_DISABLED when sync_enabled_
// is false even if state_ is REMOTE_SERVICE_OK).
RemoteServiceState state_;
// Indicates if sync is enabled or not. This flag can be turned on or
// off by SetSyncEnabled() method. To start synchronization
// this needs to be true and state_ needs to be REMOTE_SERVICE_OK.
bool sync_enabled_;
int64 largest_fetched_changestamp_;
std::map<GURL, std::string> pending_batch_sync_origins_;
// Is set to true when there's a fair possibility that we have some
// remote changes that haven't been fetched yet.
//
// This flag is set when:
// - This gets invalidation notification,
// - The service is authenticated or becomes online, and
// - The polling timer is fired.
//
// This flag is cleared when:
// - A batch or incremental sync has been started, and
// - When all pending batch sync tasks have been finished.
bool may_have_unfetched_changes_;
ObserverList<Observer> service_observers_;
ObserverList<FileStatusObserver> file_status_observers_;
RemoteChangeHandler remote_change_handler_;
RemoteChangeProcessor* remote_change_processor_;
google_apis::GDataErrorCode last_gdata_error_;
ConflictResolutionResolver conflict_resolution_resolver_;
OriginOperationQueue pending_origin_operations_;
DISALLOW_COPY_AND_ASSIGN(DriveFileSyncService);
};
} // namespace sync_file_system
#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_