// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ #define STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ #include #include #include #include "base/callback.h" #include "base/files/file.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/sequenced_task_runner_helpers.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/open_file_system_mode.h" #include "storage/browser/fileapi/plugin_private_file_system_backend.h" #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "storage/browser/fileapi/task_runner_bound_observer_list.h" #include "storage/browser/storage_browser_export.h" #include "storage/common/fileapi/file_system_types.h" namespace base { class FilePath; class SequencedTaskRunner; class SingleThreadTaskRunner; } namespace chrome { class NativeMediaFileUtilTest; } namespace storage { class QuotaManagerProxy; class SpecialStoragePolicy; } namespace net { class URLRequest; } namespace storage { class BlobURLRequestJobTest; class FileStreamReader; } namespace storage { class AsyncFileUtil; class CopyOrMoveFileValidatorFactory; class ExternalFileSystemBackend; class ExternalMountPoints; class FileStreamWriter; class FileSystemBackend; class FileSystemFileUtil; class FileSystemOperation; class FileSystemOperationRunner; class FileSystemOptions; class FileSystemQuotaUtil; class FileSystemURL; class IsolatedFileSystemBackend; class MountPoints; class QuotaReservation; class SandboxFileSystemBackend; class WatchManager; struct DefaultContextDeleter; struct FileSystemInfo; // An auto mount handler will attempt to mount the file system requested in // |url_request|. If the URL is for this auto mount handler, it returns true // and calls |callback| when the attempt is complete. If the auto mounter // does not recognize the URL, it returns false and does not call |callback|. // Called on the IO thread. typedef base::Callback& callback)> URLRequestAutoMountHandler; // This class keeps and provides a file system context for FileSystem API. // An instance of this class is created and owned by profile. class STORAGE_EXPORT FileSystemContext : public base::RefCountedThreadSafe { public: // Returns file permission policy we should apply for the given |type|. // The return value must be bitwise-or'd of FilePermissionPolicy. // // Note: if a part of a filesystem is returned via 'Isolated' mount point, // its per-filesystem permission overrides the underlying filesystem's // permission policy. static int GetPermissionPolicy(FileSystemType type); // file_task_runner is used as default TaskRunner. // Unless a FileSystemBackend is overridden in CreateFileSystemOperation, // it is used for all file operations and file related meta operations. // The code assumes that file_task_runner->RunsTasksOnCurrentThread() // returns false if the current task is not running on the thread that allows // blocking file operations (like SequencedWorkerPool implementation does). // // |external_mount_points| contains non-system external mount points available // in the context. If not NULL, it will be used during URL cracking. // |external_mount_points| may be NULL only on platforms different from // ChromeOS (i.e. platforms that don't use external_mount_point_provider). // // |additional_backends| are added to the internal backend map // to serve filesystem requests for non-regular types. // If none is given, this context only handles HTML5 Sandbox FileSystem // and Drag-and-drop Isolated FileSystem requests. // // |auto_mount_handlers| are used to resolve calls to // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted // when a filesystem: URL request is made. FileSystemContext( base::SingleThreadTaskRunner* io_task_runner, base::SequencedTaskRunner* file_task_runner, ExternalMountPoints* external_mount_points, storage::SpecialStoragePolicy* special_storage_policy, storage::QuotaManagerProxy* quota_manager_proxy, ScopedVector additional_backends, const std::vector& auto_mount_handlers, const base::FilePath& partition_path, const FileSystemOptions& options); bool DeleteDataForOriginOnFileTaskRunner(const GURL& origin_url); // Creates a new QuotaReservation for the given |origin_url| and |type|. // Returns NULL if |type| does not support quota or reservation fails. // This should be run on |default_file_task_runner_| and the returned value // should be destroyed on the runner. scoped_refptr CreateQuotaReservationOnFileTaskRunner( const GURL& origin_url, FileSystemType type); storage::QuotaManagerProxy* quota_manager_proxy() const { return quota_manager_proxy_.get(); } // Discards inflight operations in the operation runner. void Shutdown(); // Returns a quota util for a given filesystem type. This may // return NULL if the type does not support the usage tracking or // it is not a quota-managed storage. FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const; // Returns the appropriate AsyncFileUtil instance for the given |type|. AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const; // Returns the appropriate CopyOrMoveFileValidatorFactory for the given // |type|. If |error_code| is File::FILE_OK and the result is NULL, // then no validator is required. CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, base::File::Error* error_code) const; // Returns the file system backend instance for the given |type|. // This may return NULL if it is given an invalid or unsupported filesystem // type. FileSystemBackend* GetFileSystemBackend( FileSystemType type) const; // Returns the watcher manager for the given |type|. // This may return NULL if the type does not support watching. WatcherManager* GetWatcherManager(FileSystemType type) const; // Returns true for sandboxed filesystems. Currently this does // the same as GetQuotaUtil(type) != NULL. (In an assumption that // all sandboxed filesystems must cooperate with QuotaManager so that // they can get deleted) bool IsSandboxFileSystem(FileSystemType type) const; // Returns observers for the given filesystem type. const UpdateObserverList* GetUpdateObservers(FileSystemType type) const; const ChangeObserverList* GetChangeObservers(FileSystemType type) const; const AccessObserverList* GetAccessObservers(FileSystemType type) const; // Returns all registered filesystem types. void GetFileSystemTypes(std::vector* types) const; // Returns a FileSystemBackend instance for external filesystem // type, which is used only by chromeos for now. This is equivalent to // calling GetFileSystemBackend(kFileSystemTypeExternal). ExternalFileSystemBackend* external_backend() const; // Used for OpenFileSystem. typedef base::Callback OpenFileSystemCallback; // Used for ResolveURL. enum ResolvedEntryType { RESOLVED_ENTRY_FILE, RESOLVED_ENTRY_DIRECTORY, RESOLVED_ENTRY_NOT_FOUND, }; typedef base::Callback ResolveURLCallback; // Used for DeleteFileSystem and OpenPluginPrivateFileSystem. typedef base::Callback StatusCallback; // Opens the filesystem for the given |origin_url| and |type|, and dispatches // |callback| on completion. // If |create| is true this may actually set up a filesystem instance // (e.g. by creating the root directory or initializing the database // entry etc). void OpenFileSystem( const GURL& origin_url, FileSystemType type, OpenFileSystemMode mode, const OpenFileSystemCallback& callback); // Opens the filesystem for the given |url| as read-only, if the filesystem // backend referred by the URL allows opening by resolveURL. Otherwise it // fails with FILE_ERROR_SECURITY. The entry pointed by the URL can be // absent; in that case RESOLVED_ENTRY_NOT_FOUND type is returned to the // callback for indicating the absence. Can be called from any thread with // a message loop. |callback| is invoked on the caller thread. void ResolveURL( const FileSystemURL& url, const ResolveURLCallback& callback); // Attempts to mount the filesystem needed to satisfy |url_request| made // from |storage_domain|. If an appropriate file system is not found, // callback will return an error. void AttemptAutoMountForURLRequest(const net::URLRequest* url_request, const std::string& storage_domain, const StatusCallback& callback); // Deletes the filesystem for the given |origin_url| and |type|. This should // be called on the IO thread. void DeleteFileSystem( const GURL& origin_url, FileSystemType type, const StatusCallback& callback); // Creates new FileStreamReader instance to read a file pointed by the given // filesystem URL |url| starting from |offset|. |expected_modification_time| // specifies the expected last modification if the value is non-null, the // reader will check the underlying file's actual modification time to see if // the file has been modified, and if it does any succeeding read operations // should fail with ERR_UPLOAD_FILE_CHANGED error. // This method internally cracks the |url|, get an appropriate // FileSystemBackend for the URL and call the backend's CreateFileReader. // The resolved FileSystemBackend could perform further specialization // depending on the filesystem type pointed by the |url|. // At most |max_bytes_to_read| can be fetched from the file stream reader. scoped_ptr CreateFileStreamReader( const FileSystemURL& url, int64 offset, int64 max_bytes_to_read, const base::Time& expected_modification_time); // Creates new FileStreamWriter instance to write into a file pointed by // |url| from |offset|. scoped_ptr CreateFileStreamWriter( const FileSystemURL& url, int64 offset); // Creates a new FileSystemOperationRunner. scoped_ptr CreateFileSystemOperationRunner(); base::SequencedTaskRunner* default_file_task_runner() { return default_file_task_runner_.get(); } FileSystemOperationRunner* operation_runner() { return operation_runner_.get(); } const base::FilePath& partition_path() const { return partition_path_; } // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from |url|. FileSystemURL CrackURL(const GURL& url) const; // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from method // arguments. FileSystemURL CreateCrackedFileSystemURL(const GURL& origin, FileSystemType type, const base::FilePath& path) const; #if defined(OS_CHROMEOS) // Used only on ChromeOS for now. void EnableTemporaryFileSystemInIncognito(); #endif SandboxFileSystemBackendDelegate* sandbox_delegate() { return sandbox_delegate_.get(); } // Returns true if the requested url is ok to be served. // (E.g. this returns false if the context is created for incognito mode) bool CanServeURLRequest(const FileSystemURL& url) const; // This must be used to open 'plugin private' filesystem. // See "plugin_private_file_system_backend.h" for more details. void OpenPluginPrivateFileSystem( const GURL& origin_url, FileSystemType type, const std::string& filesystem_id, const std::string& plugin_id, OpenFileSystemMode mode, const StatusCallback& callback); private: typedef std::map FileSystemBackendMap; // For CreateFileSystemOperation. friend class FileSystemOperationRunner; // For sandbox_backend(). friend class content::SandboxFileSystemTestHelper; // For plugin_private_backend(). friend class content::PluginPrivateFileSystemBackendTest; // Deleters. friend struct DefaultContextDeleter; friend class base::DeleteHelper; friend class base::RefCountedThreadSafe; ~FileSystemContext(); void DeleteOnCorrectThread() const; // Creates a new FileSystemOperation instance by getting an appropriate // FileSystemBackend for |url| and calling the backend's corresponding // CreateFileSystemOperation method. // The resolved FileSystemBackend could perform further specialization // depending on the filesystem type pointed by the |url|. // // Called by FileSystemOperationRunner. FileSystemOperation* CreateFileSystemOperation( const FileSystemURL& url, base::File::Error* error_code); // For non-cracked isolated and external mount points, returns a FileSystemURL // created by cracking |url|. The url is cracked using MountPoints registered // as |url_crackers_|. If the url cannot be cracked, returns invalid // FileSystemURL. // // If the original url does not point to an isolated or external filesystem, // returns the original url, without attempting to crack it. FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const; // For initial backend_map construction. This must be called only from // the constructor. void RegisterBackend(FileSystemBackend* backend); void DidOpenFileSystemForResolveURL( const FileSystemURL& url, const ResolveURLCallback& callback, const GURL& filesystem_root, const std::string& filesystem_name, base::File::Error error); // Returns a FileSystemBackend, used only by test code. SandboxFileSystemBackend* sandbox_backend() const { return sandbox_backend_.get(); } // Used only by test code. PluginPrivateFileSystemBackend* plugin_private_backend() const { return plugin_private_backend_.get(); } scoped_refptr io_task_runner_; scoped_refptr default_file_task_runner_; scoped_refptr quota_manager_proxy_; scoped_ptr sandbox_delegate_; // Regular file system backends. scoped_ptr sandbox_backend_; scoped_ptr isolated_backend_; // Additional file system backends. scoped_ptr plugin_private_backend_; ScopedVector additional_backends_; std::vector auto_mount_handlers_; // Registered file system backends. // The map must be constructed in the constructor since it can be accessed // on multiple threads. // This map itself doesn't retain each backend's ownership; ownerships // of the backends are held by additional_backends_ or other scoped_ptr // backend fields. FileSystemBackendMap backend_map_; // External mount points visible in the file system context (excluding system // external mount points). scoped_refptr external_mount_points_; // MountPoints used to crack FileSystemURLs. The MountPoints are ordered // in order they should try to crack a FileSystemURL. std::vector url_crackers_; // The base path of the storage partition for this context. const base::FilePath partition_path_; bool is_incognito_; scoped_ptr operation_runner_; DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext); }; struct DefaultContextDeleter { static void Destruct(const FileSystemContext* context) { context->DeleteOnCorrectThread(); } }; } // namespace storage #endif // STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_