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