Home | History | Annotate | Download | only in fileapi
      1 // Copyright (c) 2012 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_H_
      6 #define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/callback.h"
     11 #include "base/files/file_path.h"
     12 #include "base/platform_file.h"
     13 #include "base/process/process.h"
     14 #include "webkit/browser/fileapi/file_system_operation_context.h"
     15 #include "webkit/browser/webkit_storage_browser_export.h"
     16 #include "webkit/common/fileapi/directory_entry.h"
     17 
     18 namespace base {
     19 class Time;
     20 }
     21 
     22 namespace net {
     23 class URLRequest;
     24 }
     25 
     26 namespace webkit_blob {
     27 class ShareableFileReference;
     28 }
     29 
     30 class GURL;
     31 
     32 namespace fileapi {
     33 
     34 class FileSystemContext;
     35 class FileSystemURL;
     36 class FileWriterDelegate;
     37 
     38 // The interface class for FileSystemOperation implementations.
     39 //
     40 // This interface defines file system operations required to implement
     41 // "File API: Directories and System"
     42 // http://www.w3.org/TR/file-system-api/
     43 //
     44 // DESIGN NOTES
     45 //
     46 // This class is designed to
     47 //
     48 // 1) Serve one-time file system operation per instance.  Only one
     49 // method(CreateFile, CreateDirectory, Copy, Move, DirectoryExists,
     50 // GetMetadata, ReadDirectory and Remove) may be called during the
     51 // lifetime of this object and it should be called no more than once.
     52 //
     53 // 2) Deliver the results of operations to the client via the callback function
     54 // passed as the last parameter of the method.
     55 //
     56 // Note that it is valid to delete an operation while it is running.
     57 // The callback will NOT be fired if the operation is deleted before
     58 // it gets called.
     59 class FileSystemOperation {
     60  public:
     61   WEBKIT_STORAGE_BROWSER_EXPORT static FileSystemOperation* Create(
     62       const FileSystemURL& url,
     63       FileSystemContext* file_system_context,
     64       scoped_ptr<FileSystemOperationContext> operation_context);
     65 
     66   virtual ~FileSystemOperation() {}
     67 
     68   // Used for CreateFile(), etc. |result| is the return code of the operation.
     69   typedef base::Callback<void(base::PlatformFileError result)> StatusCallback;
     70 
     71   // Used for GetMetadata(). |result| is the return code of the operation,
     72   // |file_info| is the obtained file info.
     73   typedef base::Callback<
     74       void(base::PlatformFileError result,
     75            const base::PlatformFileInfo& file_info)> GetMetadataCallback;
     76 
     77   // Used for OpenFile(). |result| is the return code of the operation.
     78   // |on_close_callback| will be called after the file is closed in the child
     79   // process. It can be null, if no operation is needed on closing a file.
     80   typedef base::Callback<
     81       void(base::PlatformFileError result,
     82            base::PlatformFile file,
     83            const base::Closure& on_close_callback)> OpenFileCallback;
     84 
     85   // Used for ReadDirectoryCallback.
     86   typedef std::vector<DirectoryEntry> FileEntryList;
     87 
     88   // Used for ReadDirectory(). |result| is the return code of the operation,
     89   // |file_list| is the list of files read, and |has_more| is true if some files
     90   // are yet to be read.
     91   typedef base::Callback<
     92       void(base::PlatformFileError result,
     93            const FileEntryList& file_list,
     94            bool has_more)> ReadDirectoryCallback;
     95 
     96   // Used for CreateSnapshotFile(). (Please see the comment at
     97   // CreateSnapshotFile() below for how the method is called)
     98   // |result| is the return code of the operation.
     99   // |file_info| is the metadata of the snapshot file created.
    100   // |platform_path| is the path to the snapshot file created.
    101   //
    102   // The snapshot file could simply be of the local file pointed by the given
    103   // filesystem URL in local filesystem cases; remote filesystems
    104   // may want to download the file into a temporary snapshot file and then
    105   // return the metadata of the temporary file.
    106   //
    107   // |file_ref| is used to manage the lifetime of the returned
    108   // snapshot file.  It can be set to let the chromium backend take
    109   // care of the life time of the snapshot file.  Otherwise (if the returned
    110   // file does not require any handling) the implementation can just
    111   // return NULL.  In a more complex case, the implementaiton can manage
    112   // the lifetime of the snapshot file on its own (e.g. by its cache system)
    113   // but also can be notified via the reference when the file becomes no
    114   // longer necessary in the javascript world.
    115   // Please see the comment for ShareableFileReference for details.
    116   //
    117   typedef base::Callback<
    118       void(base::PlatformFileError result,
    119            const base::PlatformFileInfo& file_info,
    120            const base::FilePath& platform_path,
    121            const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref)>
    122           SnapshotFileCallback;
    123 
    124   // Used for progress update callback for Copy().
    125   //
    126   // BEGIN_COPY_ENTRY is fired for each copy creation beginning (for both
    127   // file and directory).
    128   // The |source_url| is the URL of the source entry. |size| should not be
    129   // used.
    130   //
    131   // END_COPY_ENTRY is fired for each copy creation finishing (for both
    132   // file and directory).
    133   // The |source_url| is the URL of the source entry. The |destination_url| is
    134   // the URL of the destination entry. |size| should not be used.
    135   //
    136   // PROGRESS is fired periodically during file copying (not fired for
    137   // directory copy).
    138   // The |source_url| is the URL of the source file. |size| is the number
    139   // of cumulative copied bytes for the currently copied file.
    140   // Both at beginning and ending of file copying, PROGRESS event should be
    141   // called. At beginning, |size| should be 0. At ending, |size| should be
    142   // the size of the file.
    143   //
    144   // Here is an example callback sequence of recursive copy. Suppose
    145   // there are a/b/c.txt (100 bytes) and a/b/d.txt (200 bytes), and trying to
    146   // copy a to x recursively, then the progress update sequence will be:
    147   //
    148   // BEGIN_COPY_ENTRY a  (starting create "a" directory in x/).
    149   // END_COPY_ENTRY a x/a (creating "a" directory in x/ is finished).
    150   //
    151   // BEGIN_COPY_ENTRY a/b (starting create "b" directory in x/a).
    152   // END_COPY_ENTRY a/b x/a/b (creating "b" directory in x/a/ is finished).
    153   //
    154   // BEGIN_COPY_ENTRY a/b/c.txt (starting to copy "c.txt" in x/a/b/).
    155   // PROGRESS a/b/c.txt 0 (The first PROGRESS's |size| should be 0).
    156   // PROGRESS a/b/c.txt 10
    157   //    :
    158   // PROGRESS a/b/c.txt 90
    159   // PROGRESS a/b/c.txt 100 (The last PROGRESS's |size| should be the size of
    160   //                         the file).
    161   // END_COPY_ENTRY a/b/c.txt x/a/b/c.txt (copying "c.txt" is finished).
    162   //
    163   // BEGIN_COPY_ENTRY a/b/d.txt (starting to copy "d.txt" in x/a/b).
    164   // PROGRESS a/b/d.txt 0 (The first PROGRESS's |size| should be 0).
    165   // PROGRESS a/b/d.txt 10
    166   //    :
    167   // PROGRESS a/b/d.txt 190
    168   // PROGRESS a/b/d.txt 200 (The last PROGRESS's |size| should be the size of
    169   //                         the file).
    170   // END_COPY_ENTRY a/b/d.txt x/a/b/d.txt (copy "d.txt" is finished).
    171   //
    172   // Note that event sequence of a/b/c.txt and a/b/d.txt can be interlaced,
    173   // because they can be done in parallel. Also PROGRESS events are optional,
    174   // so they may not be appeared.
    175   // All the progress callback invocation should be done before StatusCallback
    176   // given to the Copy is called. Especially if an error is found before first
    177   // progres callback invocation, the progress callback may NOT invoked for the
    178   // copy.
    179   //
    180   // Note for future extension. Currently this callback is only supported on
    181   // Copy(). We can extend this to Move(), because Move() is sometimes
    182   // implemented as "copy then delete."
    183   // In more precise, Move() usually can be implemented either 1) by updating
    184   // the metadata of resource (e.g. root of moving directory tree), or 2) by
    185   // copying directory tree and them removing the source tree.
    186   // For 1)'s case, we can simply add BEGIN_MOVE_ENTRY and END_MOVE_ENTRY
    187   // for root directory.
    188   // For 2)'s case, we can add BEGIN_DELETE_ENTRY and END_DELETE_ENTRY for each
    189   // entry.
    190   // For both cases, we probably won't need to use PROGRESS event because
    191   // these operations should be done quickly (at least much faster than copying
    192   // usually).
    193   enum CopyProgressType {
    194     BEGIN_COPY_ENTRY,
    195     END_COPY_ENTRY,
    196     PROGRESS,
    197   };
    198   typedef base::Callback<void(CopyProgressType type,
    199                               const FileSystemURL& source_url,
    200                               const FileSystemURL& destination_url,
    201                               int64 size)>
    202       CopyProgressCallback;
    203 
    204   // Used for CopyFileLocal() to report progress update.
    205   // |size| is the cumulative copied bytes for the copy.
    206   // At the beginning the progress callback should be called with |size| = 0,
    207   // and also at the ending the progress callback should be called with |size|
    208   // set to the copied file size.
    209   typedef base::Callback<void(int64 size)> CopyFileProgressCallback;
    210 
    211   // The option for copy or move operation.
    212   enum CopyOrMoveOption {
    213     // No additional operation.
    214     OPTION_NONE,
    215 
    216     // Preserves last modified time if possible. If the operation to update
    217     // last modified time is not supported on the file system for the
    218     // destination file, this option would be simply ignored (i.e. Copy would
    219     // be successfully done without preserving last modified time).
    220     OPTION_PRESERVE_LAST_MODIFIED,
    221   };
    222 
    223   // Used for Write().
    224   typedef base::Callback<void(base::PlatformFileError result,
    225                               int64 bytes,
    226                               bool complete)> WriteCallback;
    227 
    228   // Creates a file at |path|. If |exclusive| is true, an error is raised
    229   // in case a file is already present at the URL.
    230   virtual void CreateFile(const FileSystemURL& path,
    231                           bool exclusive,
    232                           const StatusCallback& callback) = 0;
    233 
    234   // Creates a directory at |path|. If |exclusive| is true, an error is
    235   // raised in case a directory is already present at the URL. If
    236   // |recursive| is true, create parent directories as needed just like
    237   // mkdir -p does.
    238   virtual void CreateDirectory(const FileSystemURL& path,
    239                                bool exclusive,
    240                                bool recursive,
    241                                const StatusCallback& callback) = 0;
    242 
    243   // Copies a file or directory from |src_path| to |dest_path|. If
    244   // |src_path| is a directory, the contents of |src_path| are copied to
    245   // |dest_path| recursively. A new file or directory is created at
    246   // |dest_path| as needed.
    247   // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
    248   // comment for details.
    249   // |progress_callback| is periodically called to report the progress
    250   // update. See also the comment of CopyProgressCallback. This callback is
    251   // optional.
    252   //
    253   // For recursive case this internally creates new FileSystemOperations and
    254   // calls:
    255   // - ReadDirectory, CopyFileLocal and CreateDirectory
    256   //   for same-filesystem case, or
    257   // - ReadDirectory and CreateSnapshotFile on source filesystem and
    258   //   CopyInForeignFile and CreateDirectory on dest filesystem
    259   //   for cross-filesystem case.
    260   //
    261   virtual void Copy(const FileSystemURL& src_path,
    262                     const FileSystemURL& dest_path,
    263                     CopyOrMoveOption option,
    264                     const CopyProgressCallback& progress_callback,
    265                     const StatusCallback& callback) = 0;
    266 
    267   // Moves a file or directory from |src_path| to |dest_path|. A new file
    268   // or directory is created at |dest_path| as needed.
    269   // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
    270   // comment for details.
    271   //
    272   // For recursive case this internally creates new FileSystemOperations and
    273   // calls:
    274   // - ReadDirectory, MoveFileLocal, CreateDirectory and Remove
    275   //   for same-filesystem case, or
    276   // - ReadDirectory, CreateSnapshotFile and Remove on source filesystem and
    277   //   CopyInForeignFile and CreateDirectory on dest filesystem
    278   //   for cross-filesystem case.
    279   //
    280   virtual void Move(const FileSystemURL& src_path,
    281                     const FileSystemURL& dest_path,
    282                     CopyOrMoveOption option,
    283                     const StatusCallback& callback) = 0;
    284 
    285   // Checks if a directory is present at |path|.
    286   virtual void DirectoryExists(const FileSystemURL& path,
    287                                const StatusCallback& callback) = 0;
    288 
    289   // Checks if a file is present at |path|.
    290   virtual void FileExists(const FileSystemURL& path,
    291                           const StatusCallback& callback) = 0;
    292 
    293   // Gets the metadata of a file or directory at |path|.
    294   virtual void GetMetadata(const FileSystemURL& path,
    295                            const GetMetadataCallback& callback) = 0;
    296 
    297   // Reads contents of a directory at |path|.
    298   virtual void ReadDirectory(const FileSystemURL& path,
    299                              const ReadDirectoryCallback& callback) = 0;
    300 
    301   // Removes a file or directory at |path|. If |recursive| is true, remove
    302   // all files and directories under the directory at |path| recursively.
    303   virtual void Remove(const FileSystemURL& path, bool recursive,
    304                       const StatusCallback& callback) = 0;
    305 
    306   // Writes the data read from |blob_request| using |writer_delegate|.
    307   virtual void Write(
    308     const FileSystemURL& url,
    309     scoped_ptr<FileWriterDelegate> writer_delegate,
    310     scoped_ptr<net::URLRequest> blob_request,
    311     const WriteCallback& callback) = 0;
    312 
    313   // Truncates a file at |path| to |length|. If |length| is larger than
    314   // the original file size, the file will be extended, and the extended
    315   // part is filled with null bytes.
    316   virtual void Truncate(const FileSystemURL& path, int64 length,
    317                         const StatusCallback& callback) = 0;
    318 
    319   // Tries to cancel the current operation [we support cancelling write or
    320   // truncate only]. Reports failure for the current operation, then reports
    321   // success for the cancel operation itself via the |cancel_dispatcher|.
    322   //
    323   // E.g. a typical cancel implementation would look like:
    324   //
    325   //   virtual void SomeOperationImpl::Cancel(
    326   //       const StatusCallback& cancel_callback) {
    327   //     // Abort the current inflight operation first.
    328   //     ...
    329   //
    330   //     // Dispatch ABORT error for the current operation by invoking
    331   //     // the callback function for the ongoing operation,
    332   //     operation_callback.Run(base::PLATFORM_FILE_ERROR_ABORT, ...);
    333   //
    334   //     // Dispatch 'success' for the cancel (or dispatch appropriate
    335   //     // error code with DidFail() if the cancel has somehow failed).
    336   //     cancel_callback.Run(base::PLATFORM_FILE_OK);
    337   //   }
    338   //
    339   // Note that, for reporting failure, the callback function passed to a
    340   // cancellable operations are kept around with the operation instance
    341   // (as |operation_callback_| in the code example).
    342   virtual void Cancel(const StatusCallback& cancel_callback) = 0;
    343 
    344   // Modifies timestamps of a file or directory at |path| with
    345   // |last_access_time| and |last_modified_time|. The function DOES NOT
    346   // create a file unlike 'touch' command on Linux.
    347   //
    348   // This function is used only by Pepper as of writing.
    349   virtual void TouchFile(const FileSystemURL& path,
    350                          const base::Time& last_access_time,
    351                          const base::Time& last_modified_time,
    352                          const StatusCallback& callback) = 0;
    353 
    354   // Opens a file at |path| with |file_flags|, where flags are OR'ed
    355   // values of base::PlatformFileFlags.
    356   //
    357   // This function is used only by Pepper as of writing.
    358   virtual void OpenFile(const FileSystemURL& path,
    359                         int file_flags,
    360                         const OpenFileCallback& callback) = 0;
    361 
    362   // Creates a local snapshot file for a given |path| and returns the
    363   // metadata and platform path of the snapshot file via |callback|.
    364   // In local filesystem cases the implementation may simply return
    365   // the metadata of the file itself (as well as GetMetadata does),
    366   // while in remote filesystem case the backend may want to download the file
    367   // into a temporary snapshot file and return the metadata of the
    368   // temporary file.  Or if the implementaiton already has the local cache
    369   // data for |path| it can simply return the path to the cache.
    370   virtual void CreateSnapshotFile(const FileSystemURL& path,
    371                                   const SnapshotFileCallback& callback) = 0;
    372 
    373   // Copies in a single file from a different filesystem.
    374   //
    375   // This returns:
    376   // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_file_path|
    377   //   or the parent directory of |dest_url| does not exist.
    378   // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
    379   //   is not a file.
    380   // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and
    381   //   its parent path is a file.
    382   //
    383   virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path,
    384                                  const FileSystemURL& dest_url,
    385                                  const StatusCallback& callback) = 0;
    386 
    387   // Removes a single file.
    388   //
    389   // This returns:
    390   // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist.
    391   // - PLATFORM_FILE_ERROR_NOT_A_FILE if |url| is not a file.
    392   //
    393   virtual void RemoveFile(const FileSystemURL& url,
    394                           const StatusCallback& callback) = 0;
    395 
    396   // Removes a single empty directory.
    397   //
    398   // This returns:
    399   // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist.
    400   // - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory.
    401   // - PLATFORM_FILE_ERROR_NOT_EMPTY if |url| is not empty.
    402   //
    403   virtual void RemoveDirectory(const FileSystemURL& url,
    404                                const StatusCallback& callback) = 0;
    405 
    406   // Copies a file from |src_url| to |dest_url|.
    407   // This must be called for files that belong to the same filesystem
    408   // (i.e. type() and origin() of the |src_url| and |dest_url| must match).
    409   // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
    410   // comment for details.
    411   // |progress_callback| is periodically called to report the progress
    412   // update. See also the comment of CopyFileProgressCallback. This callback is
    413   // optional.
    414   //
    415   // This returns:
    416   // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
    417   //   or the parent directory of |dest_url| does not exist.
    418   // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
    419   // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
    420   //   is not a file.
    421   // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and
    422   //   its parent path is a file.
    423   //
    424   virtual void CopyFileLocal(const FileSystemURL& src_url,
    425                              const FileSystemURL& dest_url,
    426                              CopyOrMoveOption option,
    427                              const CopyFileProgressCallback& progress_callback,
    428                              const StatusCallback& callback) = 0;
    429 
    430   // Moves a local file from |src_url| to |dest_url|.
    431   // This must be called for files that belong to the same filesystem
    432   // (i.e. type() and origin() of the |src_url| and |dest_url| must match).
    433   // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
    434   // comment for details.
    435   //
    436   // This returns:
    437   // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
    438   //   or the parent directory of |dest_url| does not exist.
    439   // - PLATFORM_FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
    440   // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
    441   //   is not a file.
    442   // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and
    443   //   its parent path is a file.
    444   //
    445   virtual void MoveFileLocal(const FileSystemURL& src_url,
    446                              const FileSystemURL& dest_url,
    447                              CopyOrMoveOption option,
    448                              const StatusCallback& callback) = 0;
    449 
    450   // Synchronously gets the platform path for the given |url|.
    451   // This may fail if the given |url|'s filesystem type is neither
    452   // temporary nor persistent.
    453   // In such a case, base::PLATFORM_FILE_ERROR_INVALID_OPERATION will be
    454   // returned.
    455   virtual base::PlatformFileError SyncGetPlatformPath(
    456       const FileSystemURL& url,
    457       base::FilePath* platform_path) = 0;
    458 
    459  protected:
    460   // Used only for internal assertions.
    461   enum OperationType {
    462     kOperationNone,
    463     kOperationCreateFile,
    464     kOperationCreateDirectory,
    465     kOperationCreateSnapshotFile,
    466     kOperationCopy,
    467     kOperationCopyInForeignFile,
    468     kOperationMove,
    469     kOperationDirectoryExists,
    470     kOperationFileExists,
    471     kOperationGetMetadata,
    472     kOperationReadDirectory,
    473     kOperationRemove,
    474     kOperationWrite,
    475     kOperationTruncate,
    476     kOperationTouchFile,
    477     kOperationOpenFile,
    478     kOperationCloseFile,
    479     kOperationGetLocalPath,
    480     kOperationCancel,
    481   };
    482 };
    483 
    484 }  // namespace fileapi
    485 
    486 #endif  // WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_H_
    487