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 google_apis::GDataErrorCode error, 111 scoped_ptr<google_apis::ResourceEntry> entry); 112 void DidUpdateDatabaseForRemoteMetadata(const SyncStatusCallback& callback, 113 SyncStatusCode status); 114 115 // This implements the body of the HandleNewFile and HandleContentUpdate. 116 // If the file doesn't have corresponding local file: 117 // - Dispatch to DownloadFile. 118 // Else, if the local file doesn't have local change: 119 // - Dispatch to DownloadFile if the local file is a regular file. 120 // - If the local file is a folder, handle this case as a conflict. Lower 121 // the priority of the tracker, and defer further handling to 122 // local-to-remote change. 123 // Else: 124 // # The file has local modification. 125 // - Handle this case as a conflict. Lower the priority of the tracker, and 126 // defer further handling to local-to-remote change. 127 void DidPrepareForAddOrUpdateFile(const SyncStatusCallback& callback, 128 SyncStatusCode status); 129 130 // Handles remotely added folder. Needs Prepare() call. 131 // TODO(tzik): Write details and implement this. 132 void HandleFolderUpdate(const SyncStatusCallback& callback); 133 void DidPrepareForFolderUpdate(const SyncStatusCallback& callback, 134 SyncStatusCode status); 135 136 void HandleSyncRootDeletion(const SyncStatusCallback& callback); 137 138 // Handles deleted remote file. Needs Prepare() call. 139 // If the deleted tracker is the sync-root: 140 // - TODO(tzik): Needs special handling. 141 // Else, if the deleted tracker is a app-root: 142 // - TODO(tzik): Needs special handling. 143 // Else, if the local file is already deleted: 144 // - Do nothing anymore to the local, call SyncCompleted(). 145 // Else, if the local file is modified: 146 // - Do nothing to the local file, call SyncCompleted(). 147 // Else, if the local file is not modified: 148 // - Delete local file. 149 // # Note: if the local file is a folder, delete recursively. 150 void HandleDeletion(const SyncStatusCallback& callback); 151 void DidPrepareForDeletion(const SyncStatusCallback& callback, 152 SyncStatusCode status); 153 154 // Handles new file. Needs Prepare() call. 155 void HandleContentUpdate(const SyncStatusCallback& callback); 156 157 void ListFolderContent(const SyncStatusCallback& callback); 158 void DidListFolderContent( 159 const SyncStatusCallback& callback, 160 scoped_ptr<FileIDList> children, 161 google_apis::GDataErrorCode error, 162 scoped_ptr<google_apis::ResourceList> resource_list); 163 164 void SyncCompleted(const SyncStatusCallback& callback, SyncStatusCode status); 165 void FinalizeSync(const SyncStatusCallback& callback, SyncStatusCode status); 166 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 drive::DriveServiceInterface* drive_service(); 192 MetadataDatabase* metadata_database(); 193 RemoteChangeProcessor* remote_change_processor(); 194 195 SyncEngineContext* sync_context_; // Not owned. 196 197 scoped_ptr<FileTracker> dirty_tracker_; 198 scoped_ptr<FileMetadata> remote_metadata_; 199 200 fileapi::FileSystemURL url_; 201 SyncAction sync_action_; 202 203 bool prepared_; 204 bool sync_root_deletion_; 205 206 scoped_ptr<SyncFileMetadata> local_metadata_; 207 scoped_ptr<FileChangeList> local_changes_; 208 209 base::WeakPtrFactory<RemoteToLocalSyncer> weak_ptr_factory_; 210 211 DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncer); 212}; 213 214} // namespace drive_backend 215} // namespace sync_file_system 216 217#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_ 218