1// Copyright (c) 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 STORAGE_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_
6#define STORAGE_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_
7
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/callback_forward.h"
12#include "base/files/file.h"
13#include "base/files/file_util_proxy.h"
14#include "base/memory/scoped_ptr.h"
15#include "storage/browser/fileapi/file_system_operation.h"
16#include "storage/browser/storage_browser_export.h"
17#include "storage/common/fileapi/directory_entry.h"
18
19namespace base {
20class Time;
21}
22
23namespace storage {
24class ShareableFileReference;
25}
26
27namespace storage {
28
29class FileSystemOperationContext;
30class FileSystemURL;
31
32// An interface which provides filesystem-specific file operations for
33// FileSystemOperationImpl.
34//
35// Each filesystem which needs to be dispatched from FileSystemOperationImpl
36// must implement this interface or a synchronous version of interface:
37// FileSystemFileUtil.
38//
39// As far as an instance of this class is owned by a FileSystemBackend
40// (which is owned by FileSystemContext), it's guaranteed that this instance's
41// alive while FileSystemOperationContext given to each operation is kept
42// alive. (Note that this instance might be freed on different thread
43// from the thread it is created.)
44//
45// It is NOT valid to give null callback to this class, and implementors
46// can assume that they don't get any null callbacks.
47//
48class AsyncFileUtil {
49 public:
50  typedef base::Callback<void(base::File::Error result)> StatusCallback;
51
52  // |on_close_callback| will be called after the |file| is closed in the
53  // child process. |on_close_callback|.is_null() can be true, if no operation
54  // is needed on closing the file.
55  typedef base::Callback<
56      void(base::File file,
57           const base::Closure& on_close_callback)> CreateOrOpenCallback;
58
59  typedef base::Callback<
60      void(base::File::Error result,
61           bool created)> EnsureFileExistsCallback;
62
63  typedef base::Callback<
64      void(base::File::Error result,
65           const base::File::Info& file_info)> GetFileInfoCallback;
66
67  typedef std::vector<DirectoryEntry> EntryList;
68  typedef base::Callback<
69      void(base::File::Error result,
70           const EntryList& file_list,
71           bool has_more)> ReadDirectoryCallback;
72
73  typedef base::Callback<
74      void(base::File::Error result,
75           const base::File::Info& file_info,
76           const base::FilePath& platform_path,
77           const scoped_refptr<storage::ShareableFileReference>& file_ref)>
78      CreateSnapshotFileCallback;
79
80  typedef base::Callback<void(int64 size)> CopyFileProgressCallback;
81
82  typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
83
84  // Creates an AsyncFileUtil instance which performs file operations on
85  // local native file system. The created instance assumes
86  // FileSystemURL::path() has the target platform path.
87  STORAGE_EXPORT static AsyncFileUtil*
88      CreateForLocalFileSystem();
89
90  AsyncFileUtil() {}
91  virtual ~AsyncFileUtil() {}
92
93  // Creates or opens a file with the given flags.
94  // If File::FLAG_CREATE is set in |file_flags| it always tries to create
95  // a new file at the given |url| and calls back with
96  // File::FILE_ERROR_FILE_EXISTS if the |url| already exists.
97  //
98  // FileSystemOperationImpl::OpenFile calls this.
99  // This is used only by Pepper/NaCl File API.
100  //
101  virtual void CreateOrOpen(
102      scoped_ptr<FileSystemOperationContext> context,
103      const FileSystemURL& url,
104      int file_flags,
105      const CreateOrOpenCallback& callback) = 0;
106
107  // Ensures that the given |url| exist.  This creates a empty new file
108  // at |url| if the |url| does not exist.
109  //
110  // FileSystemOperationImpl::CreateFile calls this.
111  //
112  // This reports following error code via |callback|:
113  // - File::FILE_OK and created==true if a file has not existed and
114  //   is created at |url|.
115  // - File::FILE_OK and created==false if the file already exists.
116  // - Other error code (with created=false) if a file hasn't existed yet
117  //   and there was an error while creating a new file.
118  //
119  virtual void EnsureFileExists(
120      scoped_ptr<FileSystemOperationContext> context,
121      const FileSystemURL& url,
122      const EnsureFileExistsCallback& callback) = 0;
123
124  // Creates directory at given url.
125  //
126  // FileSystemOperationImpl::CreateDirectory calls this.
127  //
128  // This reports following error code via |callback|:
129  // - File::FILE_ERROR_NOT_FOUND if the |url|'s parent directory
130  //   does not exist and |recursive| is false.
131  // - File::FILE_ERROR_EXISTS if a directory already exists at |url|
132  //   and |exclusive| is true.
133  // - File::FILE_ERROR_EXISTS if a file already exists at |url|
134  //   (regardless of |exclusive| value).
135  // - Other error code if it failed to create a directory.
136  //
137  virtual void CreateDirectory(
138      scoped_ptr<FileSystemOperationContext> context,
139      const FileSystemURL& url,
140      bool exclusive,
141      bool recursive,
142      const StatusCallback& callback) = 0;
143
144  // Retrieves the information about a file.
145  //
146  // FileSystemOperationImpl::GetMetadata calls this.
147  //
148  // This reports following error code via |callback|:
149  // - File::FILE_ERROR_NOT_FOUND if the file doesn't exist.
150  // - Other error code if there was an error while retrieving the file info.
151  //
152  virtual void GetFileInfo(
153      scoped_ptr<FileSystemOperationContext> context,
154      const FileSystemURL& url,
155      const GetFileInfoCallback& callback) = 0;
156
157  // Reads contents of a directory at |path|.
158  //
159  // FileSystemOperationImpl::ReadDirectory calls this.
160  //
161  // Note that the |name| field of each entry in |file_list|
162  // returned by |callback| should have a base file name
163  // of the entry relative to the directory, but not an absolute path.
164  //
165  // (E.g. if ReadDirectory is called for a directory
166  // 'path/to/dir' and the directory has entries 'a' and 'b',
167  // the returned |file_list| should include entries whose names
168  // are 'a' and 'b', but not '/path/to/dir/a' and '/path/to/dir/b'.)
169  //
170  // This reports following error code via |callback|:
171  // - File::FILE_ERROR_NOT_FOUND if the target directory doesn't exist.
172  // - File::FILE_ERROR_NOT_A_DIRECTORY if an entry exists at |url| but
173  //   is a file (not a directory).
174  //
175  virtual void ReadDirectory(
176      scoped_ptr<FileSystemOperationContext> context,
177      const FileSystemURL& url,
178      const ReadDirectoryCallback& callback) = 0;
179
180  // Modifies timestamps of a file or directory at |url| with
181  // |last_access_time| and |last_modified_time|. The function DOES NOT
182  // create a file unlike 'touch' command on Linux.
183  //
184  // FileSystemOperationImpl::TouchFile calls this.
185  // This is used only by Pepper/NaCl File API.
186  //
187  virtual void Touch(
188      scoped_ptr<FileSystemOperationContext> context,
189      const FileSystemURL& url,
190      const base::Time& last_access_time,
191      const base::Time& last_modified_time,
192      const StatusCallback& callback) = 0;
193
194  // Truncates a file at |path| to |length|. If |length| is larger than
195  // the original file size, the file will be extended, and the extended
196  // part is filled with null bytes.
197  //
198  // FileSystemOperationImpl::Truncate calls this.
199  //
200  // This reports following error code via |callback|:
201  // - File::FILE_ERROR_NOT_FOUND if the file doesn't exist.
202  //
203  virtual void Truncate(
204      scoped_ptr<FileSystemOperationContext> context,
205      const FileSystemURL& url,
206      int64 length,
207      const StatusCallback& callback) = 0;
208
209  // Copies a file from |src_url| to |dest_url|.
210  // This must be called for files that belong to the same filesystem
211  // (i.e. type() and origin() of the |src_url| and |dest_url| must match).
212  // |progress_callback| is a callback to report the progress update.
213  // See file_system_operations.h for details. This should be called on the
214  // same thread as where the method's called (IO thread). Calling this
215  // is optional. It is recommended to use this callback for heavier operations
216  // (such as file network downloading), so that, e.g., clients (UIs) can
217  // update its state to show progress to users. This may be a null callback.
218  //
219  // FileSystemOperationImpl::Copy calls this for same-filesystem copy case.
220  //
221  // This reports following error code via |callback|:
222  // - File::FILE_ERROR_NOT_FOUND if |src_url|
223  //   or the parent directory of |dest_url| does not exist.
224  // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
225  // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
226  //   is not a file.
227  // - File::FILE_ERROR_FAILED if |dest_url| does not exist and
228  //   its parent path is a file.
229  //
230  virtual void CopyFileLocal(
231      scoped_ptr<FileSystemOperationContext> context,
232      const FileSystemURL& src_url,
233      const FileSystemURL& dest_url,
234      CopyOrMoveOption option,
235      const CopyFileProgressCallback& progress_callback,
236      const StatusCallback& callback) = 0;
237
238  // Moves a local file from |src_url| to |dest_url|.
239  // This must be called for files that belong to the same filesystem
240  // (i.e. type() and origin() of the |src_url| and |dest_url| must match).
241  //
242  // FileSystemOperationImpl::Move calls this for same-filesystem move case.
243  //
244  // This reports following error code via |callback|:
245  // - File::FILE_ERROR_NOT_FOUND if |src_url|
246  //   or the parent directory of |dest_url| does not exist.
247  // - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
248  // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
249  //   is not a file.
250  // - File::FILE_ERROR_FAILED if |dest_url| does not exist and
251  //   its parent path is a file.
252  //
253  virtual void MoveFileLocal(
254      scoped_ptr<FileSystemOperationContext> context,
255      const FileSystemURL& src_url,
256      const FileSystemURL& dest_url,
257      CopyOrMoveOption option,
258      const StatusCallback& callback) = 0;
259
260  // Copies in a single file from a different filesystem.
261  //
262  // FileSystemOperationImpl::Copy or Move calls this for cross-filesystem
263  // cases.
264  //
265  // This reports following error code via |callback|:
266  // - File::FILE_ERROR_NOT_FOUND if |src_file_path|
267  //   or the parent directory of |dest_url| does not exist.
268  // - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
269  //   is not a file.
270  // - File::FILE_ERROR_FAILED if |dest_url| does not exist and
271  //   its parent path is a file.
272  //
273  virtual void CopyInForeignFile(
274        scoped_ptr<FileSystemOperationContext> context,
275        const base::FilePath& src_file_path,
276        const FileSystemURL& dest_url,
277        const StatusCallback& callback) = 0;
278
279  // Deletes a single file.
280  //
281  // FileSystemOperationImpl::RemoveFile calls this.
282  //
283  // This reports following error code via |callback|:
284  // - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
285  // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file.
286  //
287  virtual void DeleteFile(
288      scoped_ptr<FileSystemOperationContext> context,
289      const FileSystemURL& url,
290      const StatusCallback& callback) = 0;
291
292  // Removes a single empty directory.
293  //
294  // FileSystemOperationImpl::RemoveDirectory calls this.
295  //
296  // This reports following error code via |callback|:
297  // - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
298  // - File::FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory.
299  // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty.
300  //
301  virtual void DeleteDirectory(
302      scoped_ptr<FileSystemOperationContext> context,
303      const FileSystemURL& url,
304      const StatusCallback& callback) = 0;
305
306  // Removes a single file or a single directory with its contents
307  // (i.e. files/subdirectories under the directory).
308  //
309  // FileSystemOperationImpl::Remove calls this.
310  // On some platforms, such as Chrome OS Drive File System, recursive file
311  // deletion can be implemented more efficiently than calling DeleteFile() and
312  // DeleteDirectory() for each files/directories.
313  // This method is optional, so if not supported,
314  // File::FILE_ERROR_INVALID_OPERATION should be returned via |callback|.
315  //
316  // This reports following error code via |callback|:
317  // - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
318  // - File::FILE_ERROR_INVALID_OPERATION if this operation is not supported.
319  virtual void DeleteRecursively(
320      scoped_ptr<FileSystemOperationContext> context,
321      const FileSystemURL& url,
322      const StatusCallback& callback) = 0;
323
324  // Creates a local snapshot file for a given |url| and returns the
325  // metadata and platform path of the snapshot file via |callback|.
326  // In regular filesystem cases the implementation may simply return
327  // the metadata of the file itself (as well as GetMetadata does),
328  // while in non-regular filesystem case the backend may create a
329  // temporary snapshot file which holds the file data and return
330  // the metadata of the temporary file.
331  //
332  // In the callback, it returns:
333  // |file_info| is the metadata of the snapshot file created.
334  // |platform_path| is the full absolute platform path to the snapshot
335  // file created.  If a file is not backed by a real local file in
336  // the implementor's FileSystem, the implementor must create a
337  // local snapshot file and return the path of the created file.
338  //
339  // If implementors creates a temporary file for snapshotting and wants
340  // FileAPI backend to take care of the lifetime of the file (so that
341  // it won't get deleted while JS layer has any references to the created
342  // File/Blob object), it should return non-empty |file_ref|.
343  // Via the |file_ref| implementors can schedule a file deletion
344  // or arbitrary callbacks when the last reference of File/Blob is dropped.
345  //
346  // FileSystemOperationImpl::CreateSnapshotFile calls this.
347  //
348  // This reports following error code via |callback|:
349  // - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
350  // - File::FILE_ERROR_NOT_A_FILE if |url| exists but is a directory.
351  //
352  // The field values of |file_info| are undefined (implementation
353  // dependent) in error cases, and the caller should always
354  // check the return code.
355  virtual void CreateSnapshotFile(
356      scoped_ptr<FileSystemOperationContext> context,
357      const FileSystemURL& url,
358      const CreateSnapshotFileCallback& callback) = 0;
359
360 private:
361  DISALLOW_COPY_AND_ASSIGN(AsyncFileUtil);
362};
363
364}  // namespace storage
365
366#endif  // STORAGE_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_
367