• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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