blob: 8eb1125a1b8babaa316c24a79242a13ee97f73cc [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_REMOTE_TO_LOCAL_SYNCER_H_
#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_
#include <string>
#include <vector>
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
#include "chrome/browser/sync_file_system/remote_change_processor.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_file_metadata.h"
#include "google_apis/drive/gdata_errorcode.h"
#include "storage/browser/fileapi/file_system_url.h"
namespace drive {
class DriveServiceInterface;
}
namespace google_apis {
class FileList;
class FileResource;
class ResourceEntry;
}
namespace storage {
class ScopedFile;
}
namespace sync_file_system {
namespace drive_backend {
class MetadataDatabase;
class SyncEngineContext;
class RemoteToLocalSyncer : public SyncTask {
public:
typedef SyncTaskManager::Continuation Continuation;
// Conflicting trackers will have low priority for RemoteToLocalSyncer so that
// it should be resolved by LocatToRemoteSyncer.
explicit RemoteToLocalSyncer(SyncEngineContext* sync_context);
~RemoteToLocalSyncer() override;
void RunPreflight(scoped_ptr<SyncTaskToken> token) override;
void RunExclusive(scoped_ptr<SyncTaskToken> token);
const storage::FileSystemURL& url() const { return url_; }
SyncFileType file_type() const { return file_type_; }
SyncAction sync_action() const { return sync_action_; }
bool is_sync_root_deletion() const { return sync_root_deletion_; }
private:
typedef std::vector<std::string> FileIDList;
// TODO(tzik): Update documentation here.
//
// Dispatches remote change to handlers or to SyncCompleted() directly.
// This function uses information only in MetadataDatabase.
//
// If the tracker doesn't have remote metadata:
// # The file is listed in a folder right before this operation.
// - Dispatch to HandleMissingRemoteMetadata to fetch remote metadata.
// Else, if the tracker is not active or the dominating app-root is disabled:
// # Assume the file has remote metadata.
// - Update the tracker with |missing| flag and empty |md5|.
// Note: MetadataDatabase may activate the tracker if possible.
// Else, if the tracker doesn't have synced metadata:
// # Assume the tracker has remote metadata and the tracker is active.
// # The tracker is not yet synced ever.
// - If the file is remotely deleted, do nothing to local file and dispatch
// directly to SyncCompleted().
// - Else, if the file is a regular file, dispatch to HandleNewFile().
// - Else, if the file is a folder, dispatch to HandleFolderUpdate().
// - Else, the file should be an unsupported active file. This should not
// happen.
// Else, if the remote metadata is marked as deleted:
// # Most of the remote metadata is missing including title, kind and md5.
// - Dispatch to HandleDeletion().
// Else, if the tracker has different titles between its synced metadata and
// remote metadata:
// # Assume the tracker is active and has remote metetadata and synced
// metadata.
// # The file is remotely renamed.
// # Maybe, this can be decomposed to delete and update.
// - Dispatch to HandleRemoteRename().
// Else, if the tracker's parent is not a parent of the remote metadata:
// # The file has reorganized.
// # Maybe, this can be decomposed to delete and update.
// - Dispatch to HandreReorganize().
// Else, if the folder is a regular file and the md5 in remote metadata does
// not match the md5 in synced metadata:
// # The file is modified remotely.
// - Dispatch to HandleContentUpdate().
// Else, if the tracker is a folder and it has needs_folder_listing flag:
// - Dispatch to HandleFolderContentListing()
// Else, there should be no change to sync.
// - Dispatch to HandleOfflineSolvable()
void ResolveRemoteChange(scoped_ptr<SyncTaskToken> token);
void MoveToBackground(scoped_ptr<SyncTaskToken> token,
const Continuation& continuation);
void ContinueAsBackgroundTask(const Continuation& continuation,
scoped_ptr<SyncTaskToken> token);
// Handles missing remote metadata case.
// Fetches remote metadata and updates MetadataDatabase by that. The sync
// operation itself will be deferred to the next sync round.
// Note: if the file is not found, it should be handled as if deleted.
void HandleMissingRemoteMetadata(scoped_ptr<SyncTaskToken> token);
void DidGetRemoteMetadata(scoped_ptr<SyncTaskToken> token,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::FileResource> entry);
// This implements the body of the HandleNewFile and HandleContentUpdate.
// If the file doesn't have corresponding local file:
// - Dispatch to DownloadFile.
// Else, if the local file doesn't have local change:
// - Dispatch to DownloadFile if the local file is a regular file.
// - If the local file is a folder, handle this case as a conflict. Lower
// the priority of the tracker, and defer further handling to
// local-to-remote change.
// Else:
// # The file has local modification.
// - Handle this case as a conflict. Lower the priority of the tracker, and
// defer further handling to local-to-remote change.
void DidPrepareForAddOrUpdateFile(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status);
// Handles remotely added folder. Needs Prepare() call.
// TODO(tzik): Write details and implement this.
void HandleFolderUpdate(scoped_ptr<SyncTaskToken> token);
void DidPrepareForFolderUpdate(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status);
// Handles deleted remote file. Needs Prepare() call.
// If the deleted tracker is the sync-root:
// - TODO(tzik): Needs special handling.
// Else, if the deleted tracker is a app-root:
// - TODO(tzik): Needs special handling.
// Else, if the local file is already deleted:
// - Do nothing anymore to the local, call SyncCompleted().
// Else, if the local file is modified:
// - Do nothing to the local file, call SyncCompleted().
// Else, if the local file is not modified:
// - Delete local file.
// # Note: if the local file is a folder, delete recursively.
void HandleDeletion(scoped_ptr<SyncTaskToken> token);
void DidPrepareForDeletion(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status);
void HandleFileMove(scoped_ptr<SyncTaskToken> token);
// Handles new file. Needs Prepare() call.
void HandleContentUpdate(scoped_ptr<SyncTaskToken> token);
void ListFolderContent(scoped_ptr<SyncTaskToken> token);
void DidListFolderContent(
scoped_ptr<SyncTaskToken> token,
scoped_ptr<FileIDList> children,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::FileList> file_list);
void SyncCompleted(scoped_ptr<SyncTaskToken> token, SyncStatusCode status);
void FinalizeSync(scoped_ptr<SyncTaskToken> token, SyncStatusCode status);
void Prepare(const SyncStatusCallback& callback);
void DidPrepare(const SyncStatusCallback& callback,
SyncStatusCode status,
const SyncFileMetadata& metadata,
const FileChangeList& changes);
void DeleteLocalFile(scoped_ptr<SyncTaskToken> token);
void DownloadFile(scoped_ptr<SyncTaskToken> token);
void DidDownloadFile(scoped_ptr<SyncTaskToken> token,
storage::ScopedFile file,
google_apis::GDataErrorCode error,
const base::FilePath&);
void DidApplyDownload(scoped_ptr<SyncTaskToken> token,
storage::ScopedFile,
SyncStatusCode status);
void CreateFolder(scoped_ptr<SyncTaskToken> token);
// TODO(tzik): After we convert all callbacks to token-passing style,
// drop this function.
SyncStatusCallback SyncCompletedCallback(scoped_ptr<SyncTaskToken> token);
drive::DriveServiceInterface* drive_service();
MetadataDatabase* metadata_database();
RemoteChangeProcessor* remote_change_processor();
SyncEngineContext* sync_context_; // Not owned.
scoped_ptr<FileTracker> dirty_tracker_;
scoped_ptr<FileMetadata> remote_metadata_;
storage::FileSystemURL url_;
SyncFileType file_type_;
SyncAction sync_action_;
bool prepared_;
bool sync_root_deletion_;
scoped_ptr<SyncFileMetadata> local_metadata_;
scoped_ptr<FileChangeList> local_changes_;
base::WeakPtrFactory<RemoteToLocalSyncer> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncer);
};
} // namespace drive_backend
} // namespace sync_file_system
#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_