Home | History | Annotate | Download | only in fileapi
      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