diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-10 00:02:31 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-10 00:02:31 +0000 |
commit | 7257f2bf72f4b9ccec1c94d3d67f9bb2f7dd5e97 (patch) | |
tree | 60559748d741157e6a674f1785ceed123208547d /webkit/fileapi | |
parent | 21dc604db6a9cf07d5277e755df77629352334af (diff) | |
download | chromium_src-7257f2bf72f4b9ccec1c94d3d67f9bb2f7dd5e97.zip chromium_src-7257f2bf72f4b9ccec1c94d3d67f9bb2f7dd5e97.tar.gz chromium_src-7257f2bf72f4b9ccec1c94d3d67f9bb2f7dd5e97.tar.bz2 |
FileSystem code cleanup 2nd cut - introduce SandboxedFileSystemOperation
1. Introduced SandboxedFileSystemOperation.
2. Factored out most of the PathManager/QuotaManager related code from
FileSystemDispatcherHost to the SandboxedFileSystemOperation.
BUG=60243
TEST=none
Review URL: http://codereview.chromium.org/4054003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65598 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_system_operation.h | 89 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_context.cc | 34 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_context.h | 48 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_operation.cc | 184 | ||||
-rw-r--r-- | webkit/fileapi/sandboxed_file_system_operation.h | 108 | ||||
-rw-r--r-- | webkit/fileapi/webkit_fileapi.gypi | 4 |
6 files changed, 424 insertions, 43 deletions
diff --git a/webkit/fileapi/file_system_operation.h b/webkit/fileapi/file_system_operation.h index d76513f..01e2da1 100644 --- a/webkit/fileapi/file_system_operation.h +++ b/webkit/fileapi/file_system_operation.h @@ -37,49 +37,70 @@ class FileSystemOperation { public: FileSystemOperation(FileSystemCallbackDispatcher* dispatcher, scoped_refptr<base::MessageLoopProxy> proxy); - ~FileSystemOperation(); + virtual ~FileSystemOperation(); - void CreateFile(const FilePath& path, - bool exclusive); + virtual void CreateFile(const FilePath& path, + bool exclusive); - void CreateDirectory(const FilePath& path, - bool exclusive, - bool recursive); + virtual void CreateDirectory(const FilePath& path, + bool exclusive, + bool recursive); - void Copy(const FilePath& src_path, - const FilePath& dest_path); + virtual void Copy(const FilePath& src_path, + const FilePath& dest_path); - void Move(const FilePath& src_path, - const FilePath& dest_path); + virtual void Move(const FilePath& src_path, + const FilePath& dest_path); - void DirectoryExists(const FilePath& path); + virtual void DirectoryExists(const FilePath& path); - void FileExists(const FilePath& path); + virtual void FileExists(const FilePath& path); - void GetMetadata(const FilePath& path); + virtual void GetMetadata(const FilePath& path); - void ReadDirectory(const FilePath& path); + virtual void ReadDirectory(const FilePath& path); - void Remove(const FilePath& path, bool recursive); + virtual void Remove(const FilePath& path, bool recursive); - void Write( + virtual void Write( scoped_refptr<URLRequestContext> url_request_context, const FilePath& path, const GURL& blob_url, int64 offset); - void Truncate(const FilePath& path, int64 length); + virtual void Truncate(const FilePath& path, int64 length); - void TouchFile(const FilePath& path, + virtual void TouchFile(const FilePath& path, const base::Time& last_access_time, const base::Time& last_modified_time); // Try to cancel the current operation [we support cancelling write or // truncate only]. Report failure for the current operation, then tell the // passed-in operation to report success. - void Cancel(FileSystemOperation* cancel_operation); + virtual void Cancel(FileSystemOperation* cancel_operation); protected: - // Proxy for calling file_util_proxy methods. - scoped_refptr<base::MessageLoopProxy> proxy_; +#ifndef NDEBUG + enum OperationType { + kOperationNone, + kOperationCreateFile, + kOperationCreateDirectory, + kOperationCopy, + kOperationMove, + kOperationDirectoryExists, + kOperationFileExists, + kOperationGetMetadata, + kOperationReadDirectory, + kOperationRemove, + kOperationWrite, + kOperationTruncate, + kOperationTouchFile, + kOperationCancel, + }; + + // A flag to make sure we call operation only once per instance. + OperationType pending_operation_; +#endif + + FileSystemCallbackDispatcher* dispatcher() const { return dispatcher_.get(); } private: // Callback for CreateFile for |exclusive|=true cases. @@ -119,7 +140,11 @@ class FileSystemOperation { base::PassPlatformFile file, bool created); + // Proxy for calling file_util_proxy methods. + scoped_refptr<base::MessageLoopProxy> proxy_; + scoped_ptr<FileSystemCallbackDispatcher> dispatcher_; + base::ScopedCallbackFactory<FileSystemOperation> callback_factory_; // These are all used only by Write(). @@ -128,28 +153,6 @@ class FileSystemOperation { scoped_ptr<URLRequest> blob_request_; FileSystemOperation* cancel_operation_; -#ifndef NDEBUG - enum OperationType { - kOperationNone, - kOperationCreateFile, - kOperationCreateDirectory, - kOperationCopy, - kOperationMove, - kOperationDirectoryExists, - kOperationFileExists, - kOperationGetMetadata, - kOperationReadDirectory, - kOperationRemove, - kOperationWrite, - kOperationTruncate, - kOperationTouchFile, - kOperationCancel, - }; - - // A flag to make sure we call operation only once per instance. - OperationType pending_operation_; -#endif - DISALLOW_COPY_AND_ASSIGN(FileSystemOperation); }; diff --git a/webkit/fileapi/sandboxed_file_system_context.cc b/webkit/fileapi/sandboxed_file_system_context.cc new file mode 100644 index 0000000..b71f57c --- /dev/null +++ b/webkit/fileapi/sandboxed_file_system_context.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2010 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. + +#include "webkit/fileapi/sandboxed_file_system_context.h" + +#include "base/file_path.h" +#include "base/message_loop_proxy.h" +#include "webkit/fileapi/file_system_path_manager.h" +#include "webkit/fileapi/file_system_quota_manager.h" + +namespace fileapi { + +SandboxedFileSystemContext::SandboxedFileSystemContext( + scoped_refptr<base::MessageLoopProxy> file_message_loop, + const FilePath& profile_path, + bool is_incognito, + bool allow_file_access, + bool unlimited_quota) + : path_manager_(new FileSystemPathManager( + file_message_loop, profile_path, is_incognito, allow_file_access)), + quota_manager_(new FileSystemQuotaManager(allow_file_access, + unlimited_quota)) { +} + +SandboxedFileSystemContext::~SandboxedFileSystemContext() { +} + +void SandboxedFileSystemContext::Shutdown() { + path_manager_.reset(); + quota_manager_.reset(); +} + +} // namespace fileapi diff --git a/webkit/fileapi/sandboxed_file_system_context.h b/webkit/fileapi/sandboxed_file_system_context.h new file mode 100644 index 0000000..ad6e2b8 --- /dev/null +++ b/webkit/fileapi/sandboxed_file_system_context.h @@ -0,0 +1,48 @@ +// Copyright (c) 2010 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 WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_CONTEXT_H_ +#define WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_CONTEXT_H_ + +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" + +class FilePath; + +namespace base { +class MessageLoopProxy; +} + +namespace fileapi { + +class FileSystemPathManager; +class FileSystemQuotaManager; + +// This class keeps and provides a sandboxed file system context. +class SandboxedFileSystemContext { + public: + SandboxedFileSystemContext( + scoped_refptr<base::MessageLoopProxy> file_message_loop, + const FilePath& profile_path, + bool is_incognito, + bool allow_file_access_from_files, + bool unlimited_quota); + ~SandboxedFileSystemContext(); + + void Shutdown(); + + FileSystemPathManager* path_manager() { return path_manager_.get(); } + FileSystemQuotaManager* quota_manager() { return quota_manager_.get(); } + + private: + bool allow_file_access_from_files_; + scoped_ptr<FileSystemPathManager> path_manager_; + scoped_ptr<FileSystemQuotaManager> quota_manager_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxedFileSystemContext); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_CONTEXT_H_ diff --git a/webkit/fileapi/sandboxed_file_system_operation.cc b/webkit/fileapi/sandboxed_file_system_operation.cc new file mode 100644 index 0000000..fc77ce3 --- /dev/null +++ b/webkit/fileapi/sandboxed_file_system_operation.cc @@ -0,0 +1,184 @@ +// Copyright (c) 2010 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. + +#include "webkit/fileapi/sandboxed_file_system_operation.h" + +#include "net/url_request/url_request_context.h" +#include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/fileapi/file_system_path_manager.h" +#include "webkit/fileapi/file_system_quota_manager.h" +#include "webkit/fileapi/sandboxed_file_system_context.h" + +namespace fileapi { + +SandboxedFileSystemOperation::SandboxedFileSystemOperation( + FileSystemCallbackDispatcher* dispatcher, + scoped_refptr<base::MessageLoopProxy> proxy, + SandboxedFileSystemContext* file_system_context) + : FileSystemOperation(dispatcher, proxy), + file_system_context_(file_system_context), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + DCHECK(file_system_context_); +} + +void SandboxedFileSystemOperation::OpenFileSystem( + const GURL& origin_url, fileapi::FileSystemType type, bool create) { +#ifndef NDEBUG + DCHECK(kOperationNone == pending_operation_); + pending_operation_ = static_cast<FileSystemOperation::OperationType>( + kOperationOpenFileSystem); +#endif + + file_system_context_->path_manager()->GetFileSystemRootPath( + origin_url, type, create, + callback_factory_.NewCallback( + &SandboxedFileSystemOperation::DidGetRootPath)); +} + +void SandboxedFileSystemOperation::CreateFile( + const FilePath& path, bool exclusive) { + if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) + return; + FileSystemOperation::CreateFile(path, exclusive); +} + +void SandboxedFileSystemOperation::CreateDirectory( + const FilePath& path, bool exclusive, bool recursive) { + if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) + return; + FileSystemOperation::CreateDirectory(path, exclusive, recursive); +} + +void SandboxedFileSystemOperation::Copy( + const FilePath& src_path, const FilePath& dest_path) { + if (!VerifyFileSystemPathForRead(src_path) || + !VerifyFileSystemPathForWrite(dest_path, true /* create */, + FileSystemQuotaManager::kUnknownSize)) + return; + FileSystemOperation::Copy(src_path, dest_path); +} + +void SandboxedFileSystemOperation::Move( + const FilePath& src_path, const FilePath& dest_path) { + if (!VerifyFileSystemPathForRead(src_path) || + !VerifyFileSystemPathForWrite(dest_path, true /* create */, + FileSystemQuotaManager::kUnknownSize)) + return; + FileSystemOperation::Move(src_path, dest_path); +} + +void SandboxedFileSystemOperation::DirectoryExists(const FilePath& path) { + if (!VerifyFileSystemPathForRead(path)) + return; + FileSystemOperation::DirectoryExists(path); +} + +void SandboxedFileSystemOperation::FileExists(const FilePath& path) { + if (!VerifyFileSystemPathForRead(path)) + return; + FileSystemOperation::FileExists(path); +} + +void SandboxedFileSystemOperation::GetMetadata(const FilePath& path) { + if (!VerifyFileSystemPathForRead(path)) + return; + FileSystemOperation::GetMetadata(path); +} + +void SandboxedFileSystemOperation::ReadDirectory(const FilePath& path) { + if (!VerifyFileSystemPathForRead(path)) + return; + FileSystemOperation::ReadDirectory(path); +} + +void SandboxedFileSystemOperation::Remove( + const FilePath& path, bool recursive) { + if (!VerifyFileSystemPathForWrite(path, false /* create */, 0)) + return; + FileSystemOperation::Remove(path, recursive); +} + +void SandboxedFileSystemOperation::Write( + scoped_refptr<URLRequestContext> url_request_context, + const FilePath& path, const GURL& blob_url, int64 offset) { + if (!VerifyFileSystemPathForWrite(path, true /* create */, + FileSystemQuotaManager::kUnknownSize)) + return; + FileSystemOperation::Write(url_request_context, path, blob_url, offset); +} + +void SandboxedFileSystemOperation::Truncate( + const FilePath& path, int64 length) { + if (!VerifyFileSystemPathForWrite(path, false /* create */, 0)) + return; + FileSystemOperation::Truncate(path, length); +} + +void SandboxedFileSystemOperation::TouchFile(const FilePath& path, + const base::Time& last_access_time, + const base::Time& last_modified_time) { + if (!VerifyFileSystemPathForWrite(path, true /* create */, 0)) + return; + FileSystemOperation::TouchFile(path, last_access_time, last_modified_time); +} + +void SandboxedFileSystemOperation::DidGetRootPath( + bool success, const FilePath& path, const std::string& name) { + DCHECK(success || path.empty()); + dispatcher()->DidOpenFileSystem(name, path); +} + +bool SandboxedFileSystemOperation::VerifyFileSystemPathForRead( + const FilePath& path) { + // We may want do more checks, but for now it just checks if the given + // |path| is under the valid FileSystem root path for this host context. + if (!file_system_context_->path_manager()->CrackFileSystemPath( + path, NULL, NULL, NULL)) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + return false; + } + return true; +} + +bool SandboxedFileSystemOperation::VerifyFileSystemPathForWrite( + const FilePath& path, bool create, int64 growth) { + GURL origin_url; + FilePath virtual_path; + if (!file_system_context_->path_manager()->CrackFileSystemPath( + path, &origin_url, NULL, &virtual_path)) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + return false; + } + // Any write access is disallowed on the root path. + if (virtual_path.value().length() == 0 || + virtual_path.DirName().value() == virtual_path.value()) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + return false; + } + if (create && file_system_context_->path_manager()->IsRestrictedFileName( + path.BaseName())) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + return false; + } + // TODO(kinuko): For operations with kUnknownSize we'll eventually + // need to resolve what amount of size it's going to write. + if (!file_system_context_->quota_manager()->CheckOriginQuota( + origin_url, growth)) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); + return false; + } + return true; +} + +bool SandboxedFileSystemOperation::CheckIfFilePathIsSafe( + const FilePath& path) { + if (file_system_context_->path_manager()->IsRestrictedFileName( + path.BaseName())) { + dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); + return false; + } + return true; +} + +} // namespace fileapi diff --git a/webkit/fileapi/sandboxed_file_system_operation.h b/webkit/fileapi/sandboxed_file_system_operation.h new file mode 100644 index 0000000..088a5f3 --- /dev/null +++ b/webkit/fileapi/sandboxed_file_system_operation.h @@ -0,0 +1,108 @@ +// Copyright (c) 2010 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 WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_OPERATION_H_ +#define WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_OPERATION_H_ + +#include "base/scoped_callback_factory.h" +#include "webkit/fileapi/file_system_operation.h" +#include "webkit/fileapi/file_system_types.h" + +namespace fileapi { + +class SandboxedFileSystemContext; + +// This class provides a 'sandboxed' access to the underlying file system, +// that is: +// 1. provides OpenFileSystem method that returns a (hidden) root path +// that is given by |file_system_context|. +// 2. enforces quota and file names/paths restrictions on each operation +// via |file_system_context|. +class SandboxedFileSystemOperation : public FileSystemOperation { + public: + // This class doesn't hold a reference or ownership of |file_system_context|. + // It is the caller's responsibility to keep the pointer alive *until* + // it calls any of the operation methods. The |file_system_context| won't be + // used in the callback path and can be deleted after the operation is + // made (e.g. after one of CreateFile, CreateDirectory, Copy, etc is called). + SandboxedFileSystemOperation(FileSystemCallbackDispatcher* dispatcher, + scoped_refptr<base::MessageLoopProxy> proxy, + SandboxedFileSystemContext* file_system_context); + + void OpenFileSystem(const GURL& origin_url, + fileapi::FileSystemType type, + bool create); + + // FileSystemOperation's methods. + virtual void CreateFile(const FilePath& path, + bool exclusive); + virtual void CreateDirectory(const FilePath& path, + bool exclusive, + bool recursive); + virtual void Copy(const FilePath& src_path, + const FilePath& dest_path); + virtual void Move(const FilePath& src_path, + const FilePath& dest_path); + virtual void DirectoryExists(const FilePath& path); + virtual void FileExists(const FilePath& path); + virtual void GetMetadata(const FilePath& path); + virtual void ReadDirectory(const FilePath& path); + virtual void Remove(const FilePath& path, bool recursive); + virtual void Write( + scoped_refptr<URLRequestContext> url_request_context, + const FilePath& path, const GURL& blob_url, int64 offset); + virtual void Truncate(const FilePath& path, int64 length); + virtual void TouchFile(const FilePath& path, + const base::Time& last_access_time, + const base::Time& last_modified_time); + + private: + enum SandboxedFileSystemOperationType { + kOperationOpenFileSystem = 100, + }; + + // A callback used for OpenFileSystem. + void DidGetRootPath(bool success, + const FilePath& path, + const std::string& name); + + // Checks the validity of a given |path| for reading. + // Returns true if the given |path| is a valid FileSystem path. + // Otherwise it calls dispatcher's DidFail method with + // PLATFORM_FILE_ERROR_SECURITY and returns false. + bool VerifyFileSystemPathForRead(const FilePath& path); + + // Checks the validity of a given |path| for writing. + // Returns true if the given |path| is a valid FileSystem path, and + // its origin embedded in the path has the right to write as much as + // the given |growth|. + // Otherwise it fires dispatcher's DidFail method with + // PLATFORM_FILE_ERROR_SECURITY if the path is not valid for writing, + // or with PLATFORM_FILE_ERROR_NO_SPACE if the origin is not allowed to + // increase the usage by |growth|. + // In either case it returns false after firing DidFail. + // If |create| flag is true this also checks if the |path| contains + // any restricted names and chars. If it does, the call fires dispatcher's + // DidFail with PLATFORM_FILE_ERROR_SECURITY and returns false. + bool VerifyFileSystemPathForWrite(const FilePath& path, + bool create, + int64 growth); + + // Checks if a given |path| does not contain any restricted names/chars + // for new files. Returns true if the given |path| is safe. + // Otherwise it fires dispatcher's DidFail method with + // PLATFORM_FILE_ERROR_SECURITY and returns false. + bool CheckIfFilePathIsSafe(const FilePath& path); + + // Not owned. See the comment at the constructor. + SandboxedFileSystemContext* file_system_context_; + + base::ScopedCallbackFactory<SandboxedFileSystemOperation> callback_factory_; + + DISALLOW_COPY_AND_ASSIGN(SandboxedFileSystemOperation); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_SANDBOXED_FILE_SYSTEM_OPERATION_H_ diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index de9e612..e380a2c 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -24,6 +24,10 @@ 'file_system_types.h', 'file_writer_delegate.cc', 'file_writer_delegate.h', + 'sandboxed_file_system_context.cc', + 'sandboxed_file_system_context.h', + 'sandboxed_file_system_operation.cc', + 'sandboxed_file_system_operation.h', 'webfilewriter_base.cc', 'webfilewriter_base.h', ], |