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