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 WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ 6 #define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ 7 8 #include <map> 9 #include <set> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/id_map.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/weak_ptr.h" 16 #include "webkit/browser/blob/blob_data_handle.h" 17 #include "webkit/browser/fileapi/file_system_operation.h" 18 #include "webkit/browser/fileapi/file_system_url.h" 19 #include "webkit/browser/webkit_storage_browser_export.h" 20 21 namespace net { 22 class URLRequestContext; 23 } 24 25 namespace fileapi { 26 27 class FileSystemURL; 28 class FileSystemContext; 29 30 // A central interface for running FileSystem API operations. 31 // All operation methods take callback and returns OperationID, which is 32 // an integer value which can be used for cancelling an operation. 33 // All operation methods return kErrorOperationID if running (posting) an 34 // operation fails, in addition to dispatching the callback with an error 35 // code (therefore in most cases the caller does not need to check the 36 // returned operation ID). 37 class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner 38 : public base::SupportsWeakPtr<FileSystemOperationRunner> { 39 public: 40 typedef FileSystemOperation::GetMetadataCallback GetMetadataCallback; 41 typedef FileSystemOperation::ReadDirectoryCallback ReadDirectoryCallback; 42 typedef FileSystemOperation::SnapshotFileCallback SnapshotFileCallback; 43 typedef FileSystemOperation::StatusCallback StatusCallback; 44 typedef FileSystemOperation::WriteCallback WriteCallback; 45 typedef FileSystemOperation::OpenFileCallback OpenFileCallback; 46 typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; 47 typedef FileSystemOperation::CopyFileProgressCallback 48 CopyFileProgressCallback; 49 typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption; 50 51 typedef int OperationID; 52 53 virtual ~FileSystemOperationRunner(); 54 55 // Cancels all inflight operations. 56 void Shutdown(); 57 58 // Creates a file at |url|. If |exclusive| is true, an error is raised 59 // in case a file is already present at the URL. 60 OperationID CreateFile(const FileSystemURL& url, 61 bool exclusive, 62 const StatusCallback& callback); 63 64 OperationID CreateDirectory(const FileSystemURL& url, 65 bool exclusive, 66 bool recursive, 67 const StatusCallback& callback); 68 69 // Copies a file or directory from |src_url| to |dest_url|. If 70 // |src_url| is a directory, the contents of |src_url| are copied to 71 // |dest_url| recursively. A new file or directory is created at 72 // |dest_url| as needed. 73 // For |option| and |progress_callback|, see file_system_operation.h for 74 // details. 75 OperationID Copy(const FileSystemURL& src_url, 76 const FileSystemURL& dest_url, 77 CopyOrMoveOption option, 78 const CopyProgressCallback& progress_callback, 79 const StatusCallback& callback); 80 81 // Moves a file or directory from |src_url| to |dest_url|. A new file 82 // or directory is created at |dest_url| as needed. 83 // For |option|, see file_system_operation.h for details. 84 OperationID Move(const FileSystemURL& src_url, 85 const FileSystemURL& dest_url, 86 CopyOrMoveOption option, 87 const StatusCallback& callback); 88 89 // Checks if a directory is present at |url|. 90 OperationID DirectoryExists(const FileSystemURL& url, 91 const StatusCallback& callback); 92 93 // Checks if a file is present at |url|. 94 OperationID FileExists(const FileSystemURL& url, 95 const StatusCallback& callback); 96 97 // Gets the metadata of a file or directory at |url|. 98 OperationID GetMetadata(const FileSystemURL& url, 99 const GetMetadataCallback& callback); 100 101 // Reads contents of a directory at |url|. 102 OperationID ReadDirectory(const FileSystemURL& url, 103 const ReadDirectoryCallback& callback); 104 105 // Removes a file or directory at |url|. If |recursive| is true, remove 106 // all files and directories under the directory at |url| recursively. 107 OperationID Remove(const FileSystemURL& url, bool recursive, 108 const StatusCallback& callback); 109 110 // Writes contents of |blob_url| to |url| at |offset|. 111 // |url_request_context| is used to read contents in |blob|. 112 OperationID Write(const net::URLRequestContext* url_request_context, 113 const FileSystemURL& url, 114 scoped_ptr<webkit_blob::BlobDataHandle> blob, 115 int64 offset, 116 const WriteCallback& callback); 117 118 // Truncates a file at |url| to |length|. If |length| is larger than 119 // the original file size, the file will be extended, and the extended 120 // part is filled with null bytes. 121 OperationID Truncate(const FileSystemURL& url, int64 length, 122 const StatusCallback& callback); 123 124 // Tries to cancel the operation |id| [we support cancelling write or 125 // truncate only]. Reports failure for the current operation, then reports 126 // success for the cancel operation itself via the |callback|. 127 void Cancel(OperationID id, const StatusCallback& callback); 128 129 // Modifies timestamps of a file or directory at |url| with 130 // |last_access_time| and |last_modified_time|. The function DOES NOT 131 // create a file unlike 'touch' command on Linux. 132 // 133 // This function is used only by Pepper as of writing. 134 OperationID TouchFile(const FileSystemURL& url, 135 const base::Time& last_access_time, 136 const base::Time& last_modified_time, 137 const StatusCallback& callback); 138 139 // Opens a file at |url| with |file_flags|, where flags are OR'ed 140 // values of base::PlatformFileFlags. 141 // 142 // |peer_handle| is the process handle of a pepper plugin process, which 143 // is necessary for underlying IPC calls with Pepper plugins. 144 // 145 // This function is used only by Pepper as of writing. 146 OperationID OpenFile(const FileSystemURL& url, 147 int file_flags, 148 const OpenFileCallback& callback); 149 150 // Creates a local snapshot file for a given |url| and returns the 151 // metadata and platform url of the snapshot file via |callback|. 152 // In local filesystem cases the implementation may simply return 153 // the metadata of the file itself (as well as GetMetadata does), 154 // while in remote filesystem case the backend may want to download the file 155 // into a temporary snapshot file and return the metadata of the 156 // temporary file. Or if the implementaiton already has the local cache 157 // data for |url| it can simply return the url to the cache. 158 OperationID CreateSnapshotFile(const FileSystemURL& url, 159 const SnapshotFileCallback& callback); 160 161 // Copies in a single file from a different filesystem. 162 // 163 // This returns: 164 // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_file_path| 165 // or the parent directory of |dest_url| does not exist. 166 // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and 167 // is not a file. 168 // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and 169 // its parent path is a file. 170 // 171 OperationID CopyInForeignFile(const base::FilePath& src_local_disk_path, 172 const FileSystemURL& dest_url, 173 const StatusCallback& callback); 174 175 // Removes a single file. 176 // 177 // This returns: 178 // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. 179 // - PLATFORM_FILE_ERROR_NOT_A_FILE if |url| is not a file. 180 // 181 OperationID RemoveFile(const FileSystemURL& url, 182 const StatusCallback& callback); 183 184 // Removes a single empty directory. 185 // 186 // This returns: 187 // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. 188 // - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. 189 // - PLATFORM_FILE_ERROR_NOT_EMPTY if |url| is not empty. 190 // 191 OperationID RemoveDirectory(const FileSystemURL& url, 192 const StatusCallback& callback); 193 194 // Copies a file from |src_url| to |dest_url|. 195 // This must be called for files that belong to the same filesystem 196 // (i.e. type() and origin() of the |src_url| and |dest_url| must match). 197 // For |option| and |progress_callback|, see file_system_operation.h for 198 // details. 199 // 200 // This returns: 201 // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| 202 // or the parent directory of |dest_url| does not exist. 203 // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. 204 // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and 205 // is not a file. 206 // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and 207 // its parent path is a file. 208 // 209 OperationID CopyFileLocal(const FileSystemURL& src_url, 210 const FileSystemURL& dest_url, 211 CopyOrMoveOption option, 212 const CopyFileProgressCallback& progress_callback, 213 const StatusCallback& callback); 214 215 // Moves a local file from |src_url| to |dest_url|. 216 // This must be called for files that belong to the same filesystem 217 // (i.e. type() and origin() of the |src_url| and |dest_url| must match). 218 // For |option|, see file_system_operation.h for details. 219 // 220 // This returns: 221 // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url| 222 // or the parent directory of |dest_url| does not exist. 223 // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file. 224 // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and 225 // is not a file. 226 // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and 227 // its parent path is a file. 228 // 229 OperationID MoveFileLocal(const FileSystemURL& src_url, 230 const FileSystemURL& dest_url, 231 CopyOrMoveOption option, 232 const StatusCallback& callback); 233 234 // This is called only by pepper plugin as of writing to synchronously get 235 // the underlying platform path to upload a file in the sandboxed filesystem 236 // (e.g. TEMPORARY or PERSISTENT). 237 base::PlatformFileError SyncGetPlatformPath(const FileSystemURL& url, 238 base::FilePath* platform_path); 239 240 private: 241 class BeginOperationScoper; 242 243 struct OperationHandle { 244 OperationID id; 245 base::WeakPtr<BeginOperationScoper> scope; 246 247 OperationHandle(); 248 ~OperationHandle(); 249 }; 250 251 friend class FileSystemContext; 252 explicit FileSystemOperationRunner(FileSystemContext* file_system_context); 253 254 void DidFinish(const OperationHandle& handle, 255 const StatusCallback& callback, 256 base::PlatformFileError rv); 257 void DidGetMetadata(const OperationHandle& handle, 258 const GetMetadataCallback& callback, 259 base::PlatformFileError rv, 260 const base::PlatformFileInfo& file_info); 261 void DidReadDirectory(const OperationHandle& handle, 262 const ReadDirectoryCallback& callback, 263 base::PlatformFileError rv, 264 const std::vector<DirectoryEntry>& entries, 265 bool has_more); 266 void DidWrite(const OperationHandle& handle, 267 const WriteCallback& callback, 268 base::PlatformFileError rv, 269 int64 bytes, 270 bool complete); 271 void DidOpenFile( 272 const OperationHandle& handle, 273 const OpenFileCallback& callback, 274 base::PlatformFileError rv, 275 base::PlatformFile file, 276 const base::Closure& on_close_callback); 277 void DidCreateSnapshot( 278 const OperationHandle& handle, 279 const SnapshotFileCallback& callback, 280 base::PlatformFileError rv, 281 const base::PlatformFileInfo& file_info, 282 const base::FilePath& platform_path, 283 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); 284 285 void OnCopyProgress( 286 const OperationHandle& handle, 287 const CopyProgressCallback& callback, 288 FileSystemOperation::CopyProgressType type, 289 const FileSystemURL& source_url, 290 const FileSystemURL& dest_url, 291 int64 size); 292 293 void PrepareForWrite(OperationID id, const FileSystemURL& url); 294 void PrepareForRead(OperationID id, const FileSystemURL& url); 295 296 // These must be called at the beginning and end of any async operations. 297 OperationHandle BeginOperation(FileSystemOperation* operation, 298 base::WeakPtr<BeginOperationScoper> scope); 299 void FinishOperation(OperationID id); 300 301 // Not owned; file_system_context owns this. 302 FileSystemContext* file_system_context_; 303 304 // IDMap<FileSystemOperation, IDMapOwnPointer> operations_; 305 IDMap<FileSystemOperation, IDMapOwnPointer> operations_; 306 307 // We keep track of the file to be modified by each operation so that 308 // we can notify observers when we're done. 309 typedef std::map<OperationID, FileSystemURLSet> OperationToURLSet; 310 OperationToURLSet write_target_urls_; 311 312 // Operations that are finished but not yet fire their callbacks. 313 std::set<OperationID> finished_operations_; 314 315 // Callbacks for stray cancels whose target operation is already finished. 316 std::map<OperationID, StatusCallback> stray_cancel_callbacks_; 317 318 DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunner); 319 }; 320 321 } // namespace fileapi 322 323 #endif // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_ 324