remote_to_local_syncer.h revision 116680a4aac90f2aa7413d9095a592090648e557
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/drive_backend/sync_task.h" 15#include "chrome/browser/sync_file_system/remote_change_processor.h" 16#include "chrome/browser/sync_file_system/sync_action.h" 17#include "chrome/browser/sync_file_system/sync_callbacks.h" 18#include "chrome/browser/sync_file_system/sync_file_metadata.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 FileList; 28class FileResource; 29class ResourceEntry; 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 RunPreflight(scoped_ptr<SyncTaskToken> token) OVERRIDE; 50 void RunExclusive(scoped_ptr<SyncTaskToken> token); 51 52 const fileapi::FileSystemURL& url() const { return url_; } 53 SyncAction sync_action() const { return sync_action_; } 54 55 bool is_sync_root_deletion() const { return sync_root_deletion_; } 56 57 private: 58 typedef std::vector<std::string> FileIDList; 59 60 // TODO(tzik): Update documentation here. 61 // 62 // Dispatches remote change to handlers or to SyncCompleted() directly. 63 // This function uses information only in MetadataDatabase. 64 // 65 // If the tracker doesn't have remote metadata: 66 // # The file is listed in a folder right before this operation. 67 // - Dispatch to HandleMissingRemoteMetadata to fetch remote metadata. 68 // Else, if the tracker is not active or the dominating app-root is disabled: 69 // # Assume the file has remote metadata. 70 // - Update the tracker with |missing| flag and empty |md5|. 71 // Note: MetadataDatabase may activate the tracker if possible. 72 // Else, if the tracker doesn't have synced metadata: 73 // # Assume the tracker has remote metadata and the tracker is active. 74 // # The tracker is not yet synced ever. 75 // - If the file is remotely deleted, do nothing to local file and dispatch 76 // directly to SyncCompleted(). 77 // - Else, if the file is a regular file, dispatch to HandleNewFile(). 78 // - Else, if the file is a folder, dispatch to HandleFolderUpdate(). 79 // - Else, the file should be an unsupported active file. This should not 80 // happen. 81 // Else, if the remote metadata is marked as deleted: 82 // # Most of the remote metadata is missing including title, kind and md5. 83 // - Dispatch to HandleDeletion(). 84 // Else, if the tracker has different titles between its synced metadata and 85 // remote metadata: 86 // # Assume the tracker is active and has remote metetadata and synced 87 // metadata. 88 // # The file is remotely renamed. 89 // # Maybe, this can be decomposed to delete and update. 90 // - Dispatch to HandleRemoteRename(). 91 // Else, if the tracker's parent is not a parent of the remote metadata: 92 // # The file has reorganized. 93 // # Maybe, this can be decomposed to delete and update. 94 // - Dispatch to HandreReorganize(). 95 // Else, if the folder is a regular file and the md5 in remote metadata does 96 // not match the md5 in synced metadata: 97 // # The file is modified remotely. 98 // - Dispatch to HandleContentUpdate(). 99 // Else, if the tracker is a folder and it has needs_folder_listing flag: 100 // - Dispatch to HandleFolderContentListing() 101 // Else, there should be no change to sync. 102 // - Dispatch to HandleOfflineSolvable() 103 void ResolveRemoteChange(scoped_ptr<SyncTaskToken> token); 104 105 // Handles missing remote metadata case. 106 // Fetches remote metadata and updates MetadataDatabase by that. The sync 107 // operation itself will be deferred to the next sync round. 108 // Note: if the file is not found, it should be handled as if deleted. 109 void HandleMissingRemoteMetadata(const SyncStatusCallback& callback); 110 void DidGetRemoteMetadata(const SyncStatusCallback& callback, 111 google_apis::GDataErrorCode error, 112 scoped_ptr<google_apis::FileResource> 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::FileList> file_list); 164 165 void SyncCompleted(scoped_ptr<SyncTaskToken> token, SyncStatusCode status); 166 void FinalizeSync(scoped_ptr<SyncTaskToken> token, SyncStatusCode status); 167 168 void Prepare(const SyncStatusCallback& callback); 169 void DidPrepare(const SyncStatusCallback& callback, 170 SyncStatusCode status, 171 const SyncFileMetadata& metadata, 172 const FileChangeList& changes); 173 174 void DeleteLocalFile(const SyncStatusCallback& callback); 175 void DownloadFile(const SyncStatusCallback& callback); 176 void DidCreateTemporaryFileForDownload(const SyncStatusCallback& callback, 177 webkit_blob::ScopedFile file); 178 void DidDownloadFile(const SyncStatusCallback& callback, 179 webkit_blob::ScopedFile file, 180 google_apis::GDataErrorCode error, 181 const base::FilePath&); 182 void DidCalculateMD5ForDownload(const SyncStatusCallback& callback, 183 webkit_blob::ScopedFile file, 184 const std::string& md5); 185 void DidApplyDownload(const SyncStatusCallback& callback, 186 webkit_blob::ScopedFile, 187 SyncStatusCode status); 188 189 void CreateFolder(const SyncStatusCallback& callback); 190 191 // TODO(tzik): After we convert all callbacks to token-passing style, 192 // drop this function. 193 SyncStatusCallback SyncCompletedCallback(scoped_ptr<SyncTaskToken> token); 194 195 drive::DriveServiceInterface* drive_service(); 196 MetadataDatabase* metadata_database(); 197 RemoteChangeProcessor* remote_change_processor(); 198 199 SyncEngineContext* sync_context_; // Not owned. 200 201 scoped_ptr<FileTracker> dirty_tracker_; 202 scoped_ptr<FileMetadata> remote_metadata_; 203 204 fileapi::FileSystemURL url_; 205 SyncAction sync_action_; 206 207 bool prepared_; 208 bool sync_root_deletion_; 209 210 scoped_ptr<SyncFileMetadata> local_metadata_; 211 scoped_ptr<FileChangeList> local_changes_; 212 213 base::WeakPtrFactory<RemoteToLocalSyncer> weak_ptr_factory_; 214 215 DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncer); 216}; 217 218} // namespace drive_backend 219} // namespace sync_file_system 220 221#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_ 222