remote_to_local_syncer.h revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright 2013 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. 4 5#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_ 6#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_ 7 8#include <string> 9#include <vector> 10 11#include "base/memory/scoped_vector.h" 12#include "base/memory/weak_ptr.h" 13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 14#include "chrome/browser/sync_file_system/remote_change_processor.h" 15#include "chrome/browser/sync_file_system/sync_action.h" 16#include "chrome/browser/sync_file_system/sync_callbacks.h" 17#include "chrome/browser/sync_file_system/sync_file_metadata.h" 18#include "chrome/browser/sync_file_system/sync_task.h" 19#include "google_apis/drive/gdata_errorcode.h" 20#include "webkit/browser/fileapi/file_system_url.h" 21 22namespace drive { 23class DriveServiceInterface; 24} 25 26namespace google_apis { 27class FileResource; 28class ResourceEntry; 29class ResourceList; 30} 31 32namespace webkit_blob { 33class ScopedFile; 34} 35 36namespace sync_file_system { 37namespace drive_backend { 38 39class MetadataDatabase; 40class SyncEngineContext; 41 42class RemoteToLocalSyncer : public SyncTask { 43 public: 44 // Conflicting trackers will have low priority for RemoteToLocalSyncer so that 45 // it should be resolved by LocatToRemoteSyncer. 46 explicit RemoteToLocalSyncer(SyncEngineContext* sync_context); 47 virtual ~RemoteToLocalSyncer(); 48 49 virtual void Run(const SyncStatusCallback& callback) OVERRIDE; 50 51 const fileapi::FileSystemURL& url() const { return url_; } 52 SyncAction sync_action() const { return sync_action_; } 53 54 bool is_sync_root_deletion() const { return sync_root_deletion_; } 55 56 private: 57 typedef std::vector<std::string> FileIDList; 58 59 // TODO(tzik): Update documentation here. 60 // 61 // Dispatches remote change to handlers or to SyncCompleted() directly. 62 // This function uses information only in MetadataDatabase. 63 // 64 // If the tracker doesn't have remote metadata: 65 // # The file is listed in a folder right before this operation. 66 // - Dispatch to HandleMissingRemoteMetadata to fetch remote metadata. 67 // Else, if the tracker is not active or the dominating app-root is disabled: 68 // # Assume the file has remote metadata. 69 // - Update the tracker with |missing| flag and empty |md5|. 70 // Note: MetadataDatabase may activate the tracker if possible. 71 // Else, if the tracker doesn't have synced metadata: 72 // # Assume the tracker has remote metadata and the tracker is active. 73 // # The tracker is not yet synced ever. 74 // - If the file is remotely deleted, do nothing to local file and dispatch 75 // directly to SyncCompleted(). 76 // - Else, if the file is a regular file, dispatch to HandleNewFile(). 77 // - Else, if the file is a folder, dispatch to HandleFolderUpdate(). 78 // - Else, the file should be an unsupported active file. This should not 79 // happen. 80 // Else, if the remote metadata is marked as deleted: 81 // # Most of the remote metadata is missing including title, kind and md5. 82 // - Dispatch to HandleDeletion(). 83 // Else, if the tracker has different titles between its synced metadata and 84 // remote metadata: 85 // # Assume the tracker is active and has remote metetadata and synced 86 // metadata. 87 // # The file is remotely renamed. 88 // # Maybe, this can be decomposed to delete and update. 89 // - Dispatch to HandleRemoteRename(). 90 // Else, if the tracker's parent is not a parent of the remote metadata: 91 // # The file has reorganized. 92 // # Maybe, this can be decomposed to delete and update. 93 // - Dispatch to HandreReorganize(). 94 // Else, if the folder is a regular file and the md5 in remote metadata does 95 // not match the md5 in synced metadata: 96 // # The file is modified remotely. 97 // - Dispatch to HandleContentUpdate(). 98 // Else, if the tracker is a folder and it has needs_folder_listing flag: 99 // - Dispatch to HandleFolderContentListing() 100 // Else, there should be no change to sync. 101 // - Dispatch to HandleOfflineSolvable() 102 void ResolveRemoteChange(const SyncStatusCallback& callback); 103 104 // Handles missing remote metadata case. 105 // Fetches remote metadata and updates MetadataDatabase by that. The sync 106 // operation itself will be deferred to the next sync round. 107 // Note: if the file is not found, it should be handled as if deleted. 108 void HandleMissingRemoteMetadata(const SyncStatusCallback& callback); 109 void DidGetRemoteMetadata(const SyncStatusCallback& callback, 110 int64 change_id, 111 google_apis::GDataErrorCode error, 112 scoped_ptr<google_apis::ResourceEntry> entry); 113 void DidUpdateDatabaseForRemoteMetadata(const SyncStatusCallback& callback, 114 SyncStatusCode status); 115 116 // This implements the body of the HandleNewFile and HandleContentUpdate. 117 // If the file doesn't have corresponding local file: 118 // - Dispatch to DownloadFile. 119 // Else, if the local file doesn't have local change: 120 // - Dispatch to DownloadFile if the local file is a regular file. 121 // - If the local file is a folder, handle this case as a conflict. Lower 122 // the priority of the tracker, and defer further handling to 123 // local-to-remote change. 124 // Else: 125 // # The file has local modification. 126 // - Handle this case as a conflict. Lower the priority of the tracker, and 127 // defer further handling to local-to-remote change. 128 void DidPrepareForAddOrUpdateFile(const SyncStatusCallback& callback, 129 SyncStatusCode status); 130 131 // Handles remotely added folder. Needs Prepare() call. 132 // TODO(tzik): Write details and implement this. 133 void HandleFolderUpdate(const SyncStatusCallback& callback); 134 void DidPrepareForFolderUpdate(const SyncStatusCallback& callback, 135 SyncStatusCode status); 136 137 void HandleSyncRootDeletion(const SyncStatusCallback& callback); 138 139 // Handles deleted remote file. Needs Prepare() call. 140 // If the deleted tracker is the sync-root: 141 // - TODO(tzik): Needs special handling. 142 // Else, if the deleted tracker is a app-root: 143 // - TODO(tzik): Needs special handling. 144 // Else, if the local file is already deleted: 145 // - Do nothing anymore to the local, call SyncCompleted(). 146 // Else, if the local file is modified: 147 // - Do nothing to the local file, call SyncCompleted(). 148 // Else, if the local file is not modified: 149 // - Delete local file. 150 // # Note: if the local file is a folder, delete recursively. 151 void HandleDeletion(const SyncStatusCallback& callback); 152 void DidPrepareForDeletion(const SyncStatusCallback& callback, 153 SyncStatusCode status); 154 155 // Handles new file. Needs Prepare() call. 156 void HandleContentUpdate(const SyncStatusCallback& callback); 157 158 void ListFolderContent(const SyncStatusCallback& callback); 159 void DidListFolderContent( 160 const SyncStatusCallback& callback, 161 scoped_ptr<FileIDList> children, 162 google_apis::GDataErrorCode error, 163 scoped_ptr<google_apis::ResourceList> resource_list); 164 165 void SyncCompleted(const SyncStatusCallback& callback, SyncStatusCode status); 166 void FinalizeSync(const SyncStatusCallback& callback, SyncStatusCode status); 167 168 169 void Prepare(const SyncStatusCallback& callback); 170 void DidPrepare(const SyncStatusCallback& callback, 171 SyncStatusCode status, 172 const SyncFileMetadata& metadata, 173 const FileChangeList& changes); 174 175 void DeleteLocalFile(const SyncStatusCallback& callback); 176 void DownloadFile(const SyncStatusCallback& callback); 177 void DidCreateTemporaryFileForDownload(const SyncStatusCallback& callback, 178 webkit_blob::ScopedFile file); 179 void DidDownloadFile(const SyncStatusCallback& callback, 180 webkit_blob::ScopedFile file, 181 google_apis::GDataErrorCode error, 182 const base::FilePath&); 183 void DidCalculateMD5ForDownload(const SyncStatusCallback& callback, 184 webkit_blob::ScopedFile file, 185 const std::string& md5); 186 void DidApplyDownload(const SyncStatusCallback& callback, 187 webkit_blob::ScopedFile, 188 SyncStatusCode status); 189 190 void CreateFolder(const SyncStatusCallback& callback); 191 192 drive::DriveServiceInterface* drive_service(); 193 MetadataDatabase* metadata_database(); 194 RemoteChangeProcessor* remote_change_processor(); 195 196 SyncEngineContext* sync_context_; // Not owned. 197 198 scoped_ptr<FileTracker> dirty_tracker_; 199 scoped_ptr<FileMetadata> remote_metadata_; 200 201 fileapi::FileSystemURL url_; 202 SyncAction sync_action_; 203 204 bool prepared_; 205 bool sync_root_deletion_; 206 207 scoped_ptr<SyncFileMetadata> local_metadata_; 208 scoped_ptr<FileChangeList> local_changes_; 209 210 base::WeakPtrFactory<RemoteToLocalSyncer> weak_ptr_factory_; 211 212 DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncer); 213}; 214 215} // namespace drive_backend 216} // namespace sync_file_system 217 218#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_ 219