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 STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_
6#define STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_
7
8#include <map>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/files/file.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/memory/scoped_vector.h"
17#include "base/sequenced_task_runner_helpers.h"
18#include "storage/browser/fileapi/file_system_url.h"
19#include "storage/browser/fileapi/open_file_system_mode.h"
20#include "storage/browser/fileapi/plugin_private_file_system_backend.h"
21#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
22#include "storage/browser/fileapi/task_runner_bound_observer_list.h"
23#include "storage/browser/storage_browser_export.h"
24#include "storage/common/fileapi/file_system_types.h"
25
26namespace base {
27class FilePath;
28class SequencedTaskRunner;
29class SingleThreadTaskRunner;
30}
31
32namespace chrome {
33class NativeMediaFileUtilTest;
34}
35
36namespace storage {
37class QuotaManagerProxy;
38class SpecialStoragePolicy;
39}
40
41namespace net {
42class URLRequest;
43}
44
45namespace storage {
46class BlobURLRequestJobTest;
47class FileStreamReader;
48}
49
50namespace storage {
51
52class AsyncFileUtil;
53class CopyOrMoveFileValidatorFactory;
54class ExternalFileSystemBackend;
55class ExternalMountPoints;
56class FileStreamWriter;
57class FileSystemBackend;
58class FileSystemFileUtil;
59class FileSystemOperation;
60class FileSystemOperationRunner;
61class FileSystemOptions;
62class FileSystemQuotaUtil;
63class FileSystemURL;
64class IsolatedFileSystemBackend;
65class MountPoints;
66class QuotaReservation;
67class SandboxFileSystemBackend;
68class WatchManager;
69
70struct DefaultContextDeleter;
71struct FileSystemInfo;
72
73// An auto mount handler will attempt to mount the file system requested in
74// |url_request|. If the URL is for this auto mount handler, it returns true
75// and calls |callback| when the attempt is complete. If the auto mounter
76// does not recognize the URL, it returns false and does not call |callback|.
77// Called on the IO thread.
78typedef base::Callback<bool(
79    const net::URLRequest* url_request,
80    const FileSystemURL& filesystem_url,
81    const std::string& storage_domain,
82    const base::Callback<void(base::File::Error result)>& callback)>
83        URLRequestAutoMountHandler;
84
85// This class keeps and provides a file system context for FileSystem API.
86// An instance of this class is created and owned by profile.
87class STORAGE_EXPORT FileSystemContext
88    : public base::RefCountedThreadSafe<FileSystemContext,
89                                        DefaultContextDeleter> {
90 public:
91  // Returns file permission policy we should apply for the given |type|.
92  // The return value must be bitwise-or'd of FilePermissionPolicy.
93  //
94  // Note: if a part of a filesystem is returned via 'Isolated' mount point,
95  // its per-filesystem permission overrides the underlying filesystem's
96  // permission policy.
97  static int GetPermissionPolicy(FileSystemType type);
98
99  // file_task_runner is used as default TaskRunner.
100  // Unless a FileSystemBackend is overridden in CreateFileSystemOperation,
101  // it is used for all file operations and file related meta operations.
102  // The code assumes that file_task_runner->RunsTasksOnCurrentThread()
103  // returns false if the current task is not running on the thread that allows
104  // blocking file operations (like SequencedWorkerPool implementation does).
105  //
106  // |external_mount_points| contains non-system external mount points available
107  // in the context. If not NULL, it will be used during URL cracking.
108  // |external_mount_points| may be NULL only on platforms different from
109  // ChromeOS (i.e. platforms that don't use external_mount_point_provider).
110  //
111  // |additional_backends| are added to the internal backend map
112  // to serve filesystem requests for non-regular types.
113  // If none is given, this context only handles HTML5 Sandbox FileSystem
114  // and Drag-and-drop Isolated FileSystem requests.
115  //
116  // |auto_mount_handlers| are used to resolve calls to
117  // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted
118  // when a filesystem: URL request is made.
119  FileSystemContext(
120      base::SingleThreadTaskRunner* io_task_runner,
121      base::SequencedTaskRunner* file_task_runner,
122      ExternalMountPoints* external_mount_points,
123      storage::SpecialStoragePolicy* special_storage_policy,
124      storage::QuotaManagerProxy* quota_manager_proxy,
125      ScopedVector<FileSystemBackend> additional_backends,
126      const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers,
127      const base::FilePath& partition_path,
128      const FileSystemOptions& options);
129
130  bool DeleteDataForOriginOnFileTaskRunner(const GURL& origin_url);
131
132  // Creates a new QuotaReservation for the given |origin_url| and |type|.
133  // Returns NULL if |type| does not support quota or reservation fails.
134  // This should be run on |default_file_task_runner_| and the returned value
135  // should be destroyed on the runner.
136  scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner(
137      const GURL& origin_url,
138      FileSystemType type);
139
140  storage::QuotaManagerProxy* quota_manager_proxy() const {
141    return quota_manager_proxy_.get();
142  }
143
144  // Discards inflight operations in the operation runner.
145  void Shutdown();
146
147  // Returns a quota util for a given filesystem type.  This may
148  // return NULL if the type does not support the usage tracking or
149  // it is not a quota-managed storage.
150  FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const;
151
152  // Returns the appropriate AsyncFileUtil instance for the given |type|.
153  AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const;
154
155  // Returns the appropriate CopyOrMoveFileValidatorFactory for the given
156  // |type|.  If |error_code| is File::FILE_OK and the result is NULL,
157  // then no validator is required.
158  CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory(
159      FileSystemType type, base::File::Error* error_code) const;
160
161  // Returns the file system backend instance for the given |type|.
162  // This may return NULL if it is given an invalid or unsupported filesystem
163  // type.
164  FileSystemBackend* GetFileSystemBackend(
165      FileSystemType type) const;
166
167  // Returns the watcher manager for the given |type|.
168  // This may return NULL if the type does not support watching.
169  WatcherManager* GetWatcherManager(FileSystemType type) const;
170
171  // Returns true for sandboxed filesystems. Currently this does
172  // the same as GetQuotaUtil(type) != NULL. (In an assumption that
173  // all sandboxed filesystems must cooperate with QuotaManager so that
174  // they can get deleted)
175  bool IsSandboxFileSystem(FileSystemType type) const;
176
177  // Returns observers for the given filesystem type.
178  const UpdateObserverList* GetUpdateObservers(FileSystemType type) const;
179  const ChangeObserverList* GetChangeObservers(FileSystemType type) const;
180  const AccessObserverList* GetAccessObservers(FileSystemType type) const;
181
182  // Returns all registered filesystem types.
183  void GetFileSystemTypes(std::vector<FileSystemType>* types) const;
184
185  // Returns a FileSystemBackend instance for external filesystem
186  // type, which is used only by chromeos for now.  This is equivalent to
187  // calling GetFileSystemBackend(kFileSystemTypeExternal).
188  ExternalFileSystemBackend* external_backend() const;
189
190  // Used for OpenFileSystem.
191  typedef base::Callback<void(const GURL& root,
192                              const std::string& name,
193                              base::File::Error result)>
194      OpenFileSystemCallback;
195
196  // Used for ResolveURL.
197  enum ResolvedEntryType {
198    RESOLVED_ENTRY_FILE,
199    RESOLVED_ENTRY_DIRECTORY,
200    RESOLVED_ENTRY_NOT_FOUND,
201  };
202  typedef base::Callback<void(base::File::Error result,
203                              const FileSystemInfo& info,
204                              const base::FilePath& file_path,
205                              ResolvedEntryType type)> ResolveURLCallback;
206
207  // Used for DeleteFileSystem and OpenPluginPrivateFileSystem.
208  typedef base::Callback<void(base::File::Error result)> StatusCallback;
209
210  // Opens the filesystem for the given |origin_url| and |type|, and dispatches
211  // |callback| on completion.
212  // If |create| is true this may actually set up a filesystem instance
213  // (e.g. by creating the root directory or initializing the database
214  // entry etc).
215  void OpenFileSystem(
216      const GURL& origin_url,
217      FileSystemType type,
218      OpenFileSystemMode mode,
219      const OpenFileSystemCallback& callback);
220
221  // Opens the filesystem for the given |url| as read-only, if the filesystem
222  // backend referred by the URL allows opening by resolveURL. Otherwise it
223  // fails with FILE_ERROR_SECURITY. The entry pointed by the URL can be
224  // absent; in that case RESOLVED_ENTRY_NOT_FOUND type is returned to the
225  // callback for indicating the absence. Can be called from any thread with
226  // a message loop. |callback| is invoked on the caller thread.
227  void ResolveURL(
228      const FileSystemURL& url,
229      const ResolveURLCallback& callback);
230
231  // Attempts to mount the filesystem needed to satisfy |url_request| made
232  // from |storage_domain|. If an appropriate file system is not found,
233  // callback will return an error.
234  void AttemptAutoMountForURLRequest(const net::URLRequest* url_request,
235                                     const std::string& storage_domain,
236                                     const StatusCallback& callback);
237
238  // Deletes the filesystem for the given |origin_url| and |type|. This should
239  // be called on the IO thread.
240  void DeleteFileSystem(
241      const GURL& origin_url,
242      FileSystemType type,
243      const StatusCallback& callback);
244
245  // Creates new FileStreamReader instance to read a file pointed by the given
246  // filesystem URL |url| starting from |offset|. |expected_modification_time|
247  // specifies the expected last modification if the value is non-null, the
248  // reader will check the underlying file's actual modification time to see if
249  // the file has been modified, and if it does any succeeding read operations
250  // should fail with ERR_UPLOAD_FILE_CHANGED error.
251  // This method internally cracks the |url|, get an appropriate
252  // FileSystemBackend for the URL and call the backend's CreateFileReader.
253  // The resolved FileSystemBackend could perform further specialization
254  // depending on the filesystem type pointed by the |url|.
255  // At most |max_bytes_to_read| can be fetched from the file stream reader.
256  scoped_ptr<storage::FileStreamReader> CreateFileStreamReader(
257      const FileSystemURL& url,
258      int64 offset,
259      int64 max_bytes_to_read,
260      const base::Time& expected_modification_time);
261
262  // Creates new FileStreamWriter instance to write into a file pointed by
263  // |url| from |offset|.
264  scoped_ptr<FileStreamWriter> CreateFileStreamWriter(
265      const FileSystemURL& url,
266      int64 offset);
267
268  // Creates a new FileSystemOperationRunner.
269  scoped_ptr<FileSystemOperationRunner> CreateFileSystemOperationRunner();
270
271  base::SequencedTaskRunner* default_file_task_runner() {
272    return default_file_task_runner_.get();
273  }
274
275  FileSystemOperationRunner* operation_runner() {
276    return operation_runner_.get();
277  }
278
279  const base::FilePath& partition_path() const { return partition_path_; }
280
281  // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from |url|.
282  FileSystemURL CrackURL(const GURL& url) const;
283  // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from method
284  // arguments.
285  FileSystemURL CreateCrackedFileSystemURL(const GURL& origin,
286                                           FileSystemType type,
287                                           const base::FilePath& path) const;
288
289#if defined(OS_CHROMEOS)
290  // Used only on ChromeOS for now.
291  void EnableTemporaryFileSystemInIncognito();
292#endif
293
294  SandboxFileSystemBackendDelegate* sandbox_delegate() {
295    return sandbox_delegate_.get();
296  }
297
298  // Returns true if the requested url is ok to be served.
299  // (E.g. this returns false if the context is created for incognito mode)
300  bool CanServeURLRequest(const FileSystemURL& url) const;
301
302  // Returns true if a file in the file system should be flushed for each write
303  // completion.
304  bool ShouldFlushOnWriteCompletion(FileSystemType type) const;
305
306  // This must be used to open 'plugin private' filesystem.
307  // See "plugin_private_file_system_backend.h" for more details.
308  void OpenPluginPrivateFileSystem(
309      const GURL& origin_url,
310      FileSystemType type,
311      const std::string& filesystem_id,
312      const std::string& plugin_id,
313      OpenFileSystemMode mode,
314      const StatusCallback& callback);
315
316 private:
317  typedef std::map<FileSystemType, FileSystemBackend*>
318      FileSystemBackendMap;
319
320  // For CreateFileSystemOperation.
321  friend class FileSystemOperationRunner;
322
323  // For sandbox_backend().
324  friend class content::SandboxFileSystemTestHelper;
325
326  // For plugin_private_backend().
327  friend class content::PluginPrivateFileSystemBackendTest;
328
329  // Deleters.
330  friend struct DefaultContextDeleter;
331  friend class base::DeleteHelper<FileSystemContext>;
332  friend class base::RefCountedThreadSafe<FileSystemContext,
333                                          DefaultContextDeleter>;
334  ~FileSystemContext();
335
336  void DeleteOnCorrectThread() const;
337
338  // Creates a new FileSystemOperation instance by getting an appropriate
339  // FileSystemBackend for |url| and calling the backend's corresponding
340  // CreateFileSystemOperation method.
341  // The resolved FileSystemBackend could perform further specialization
342  // depending on the filesystem type pointed by the |url|.
343  //
344  // Called by FileSystemOperationRunner.
345  FileSystemOperation* CreateFileSystemOperation(
346      const FileSystemURL& url,
347      base::File::Error* error_code);
348
349  // For non-cracked isolated and external mount points, returns a FileSystemURL
350  // created by cracking |url|. The url is cracked using MountPoints registered
351  // as |url_crackers_|. If the url cannot be cracked, returns invalid
352  // FileSystemURL.
353  //
354  // If the original url does not point to an isolated or external filesystem,
355  // returns the original url, without attempting to crack it.
356  FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const;
357
358  // For initial backend_map construction. This must be called only from
359  // the constructor.
360  void RegisterBackend(FileSystemBackend* backend);
361
362  void DidOpenFileSystemForResolveURL(
363      const FileSystemURL& url,
364      const ResolveURLCallback& callback,
365      const GURL& filesystem_root,
366      const std::string& filesystem_name,
367      base::File::Error error);
368
369  // Returns a FileSystemBackend, used only by test code.
370  SandboxFileSystemBackend* sandbox_backend() const {
371    return sandbox_backend_.get();
372  }
373
374  // Used only by test code.
375  PluginPrivateFileSystemBackend* plugin_private_backend() const {
376    return plugin_private_backend_.get();
377  }
378
379  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
380  scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_;
381
382  scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
383
384  scoped_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_;
385
386  // Regular file system backends.
387  scoped_ptr<SandboxFileSystemBackend> sandbox_backend_;
388  scoped_ptr<IsolatedFileSystemBackend> isolated_backend_;
389
390  // Additional file system backends.
391  scoped_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_;
392  ScopedVector<FileSystemBackend> additional_backends_;
393
394  std::vector<URLRequestAutoMountHandler> auto_mount_handlers_;
395
396  // Registered file system backends.
397  // The map must be constructed in the constructor since it can be accessed
398  // on multiple threads.
399  // This map itself doesn't retain each backend's ownership; ownerships
400  // of the backends are held by additional_backends_ or other scoped_ptr
401  // backend fields.
402  FileSystemBackendMap backend_map_;
403
404  // External mount points visible in the file system context (excluding system
405  // external mount points).
406  scoped_refptr<ExternalMountPoints> external_mount_points_;
407
408  // MountPoints used to crack FileSystemURLs. The MountPoints are ordered
409  // in order they should try to crack a FileSystemURL.
410  std::vector<MountPoints*> url_crackers_;
411
412  // The base path of the storage partition for this context.
413  const base::FilePath partition_path_;
414
415  bool is_incognito_;
416
417  scoped_ptr<FileSystemOperationRunner> operation_runner_;
418
419  DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext);
420};
421
422struct DefaultContextDeleter {
423  static void Destruct(const FileSystemContext* context) {
424    context->DeleteOnCorrectThread();
425  }
426};
427
428}  // namespace storage
429
430#endif  // STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_
431