diff options
Diffstat (limited to 'webkit/browser/fileapi')
-rw-r--r-- | webkit/browser/fileapi/plugin_private_file_system_backend.cc | 297 | ||||
-rw-r--r-- | webkit/browser/fileapi/plugin_private_file_system_backend.h | 136 |
2 files changed, 433 insertions, 0 deletions
diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.cc b/webkit/browser/fileapi/plugin_private_file_system_backend.cc new file mode 100644 index 0000000..e7b6214 --- /dev/null +++ b/webkit/browser/fileapi/plugin_private_file_system_backend.cc @@ -0,0 +1,297 @@ +// Copyright 2013 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/browser/fileapi/plugin_private_file_system_backend.h" + +#include <map> + +#include "base/stl_util.h" +#include "base/synchronization/lock.h" +#include "base/task_runner_util.h" +#include "net/base/net_util.h" +#include "webkit/browser/blob/file_stream_reader.h" +#include "webkit/browser/fileapi/async_file_util_adapter.h" +#include "webkit/browser/fileapi/file_stream_writer.h" +#include "webkit/browser/fileapi/file_system_context.h" +#include "webkit/browser/fileapi/file_system_operation.h" +#include "webkit/browser/fileapi/file_system_operation_context.h" +#include "webkit/browser/fileapi/file_system_options.h" +#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/obfuscated_file_util.h" +#include "webkit/common/fileapi/file_system_util.h" + +namespace fileapi { + +class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { + public: + FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner) + : task_runner_(task_runner) {} + ~FileSystemIDToPluginMap() {} + + std::string GetPluginIDForURL(const FileSystemURL& url) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + Map::iterator found = map_.find(url.filesystem_id()); + if (url.type() != kFileSystemTypePluginPrivate || found == map_.end()) { + NOTREACHED() << "Unsupported url is given: " << url.DebugString(); + return std::string(); + } + return found->second; + } + + void RegisterFileSystem(const std::string& filesystem_id, + const std::string& plugin_id) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + DCHECK(!filesystem_id.empty() && + !ContainsKey(map_, filesystem_id)) << filesystem_id; + map_[filesystem_id] = plugin_id; + } + + void RemoveFileSystem(const std::string& filesystem_id) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + map_.erase(filesystem_id); + } + + private: + typedef std::map<std::string, std::string> Map; + scoped_refptr<base::SequencedTaskRunner> task_runner_; + Map map_; +}; + +namespace { + +const base::FilePath::CharType* kFileSystemDirectory = + SandboxFileSystemBackendDelegate::kFileSystemDirectory; +const base::FilePath::CharType* kPluginPrivateDirectory = + FILE_PATH_LITERAL("Plugins"); + +base::PlatformFileError OpenFileSystemOnFileThread( + ObfuscatedFileUtil* file_util, + PluginPrivateFileSystemBackend::FileSystemIDToPluginMap* plugin_map, + const GURL& origin_url, + const std::string& filesystem_id, + const std::string& plugin_id, + OpenFileSystemMode mode) { + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT); + file_util->GetDirectoryForOriginAndType( + origin_url, plugin_id, create, &error); + if (error != base::PLATFORM_FILE_OK) + IsolatedContext::GetInstance()->RevokeFileSystem(filesystem_id); + else + plugin_map->RegisterFileSystem(filesystem_id, plugin_id); + return error; +} + +} // namespace + +PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend( + base::SequencedTaskRunner* file_task_runner, + const base::FilePath& profile_path, + quota::SpecialStoragePolicy* special_storage_policy, + const FileSystemOptions& file_system_options) + : file_task_runner_(file_task_runner), + file_system_options_(file_system_options), + base_path_(profile_path.Append( + kFileSystemDirectory).Append(kPluginPrivateDirectory)), + plugin_map_(new FileSystemIDToPluginMap(file_task_runner)), + weak_factory_(this) { + file_util_.reset( + new AsyncFileUtilAdapter(new ObfuscatedFileUtil( + special_storage_policy, + base_path_, + file_task_runner, + base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL, + base::Owned(plugin_map_)), + std::set<std::string>()))); +} + +PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() { + if (!file_task_runner_->RunsTasksOnCurrentThread()) { + AsyncFileUtil* file_util = file_util_.release(); + if (!file_task_runner_->DeleteSoon(FROM_HERE, file_util)) + delete file_util; + } +} + +void PluginPrivateFileSystemBackend::OpenPrivateFileSystem( + const GURL& origin_url, + FileSystemType type, + const std::string& plugin_id, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) { + if (!CanHandleType(type) || file_system_options_.is_incognito()) { + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(callback, GURL(), std::string(), + base::PLATFORM_FILE_ERROR_SECURITY)); + return; + } + + // TODO(nhiroki,kinuko): This constant should be somehow shared. + const std::string name("PluginPrivate"); + std::string filesystem_id = + IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( + type, name, base::FilePath()); + + PostTaskAndReplyWithResult( + file_task_runner_.get(), + FROM_HERE, + base::Bind(&OpenFileSystemOnFileThread, + obfuscated_file_util(), plugin_map_, + origin_url, filesystem_id, plugin_id, mode), + base::Bind(callback, + GURL(GetIsolatedFileSystemRootURIString( + origin_url, filesystem_id, name)), + GetIsolatedFileSystemName(origin_url, filesystem_id))); +} + +bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const { + return type == kFileSystemTypePluginPrivate; +} + +void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) { +} + +void PluginPrivateFileSystemBackend::OpenFileSystem( + const GURL& origin_url, + FileSystemType type, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) { + // We never allow opening a new plugin-private filesystem via usual + // OpenFileSystem. + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, + base::Bind(callback, GURL(), std::string(), + base::PLATFORM_FILE_ERROR_SECURITY)); +} + +AsyncFileUtil* +PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) { + return file_util_.get(); +} + +CopyOrMoveFileValidatorFactory* +PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory( + FileSystemType type, + base::PlatformFileError* error_code) { + DCHECK(error_code); + *error_code = base::PLATFORM_FILE_OK; + return NULL; +} + +FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation( + const FileSystemURL& url, + FileSystemContext* context, + base::PlatformFileError* error_code) const { + scoped_ptr<FileSystemOperationContext> operation_context( + new FileSystemOperationContext(context)); + return FileSystemOperation::Create(url, context, operation_context.Pass()); +} + +scoped_ptr<webkit_blob::FileStreamReader> +PluginPrivateFileSystemBackend::CreateFileStreamReader( + const FileSystemURL& url, + int64 offset, + const base::Time& expected_modification_time, + FileSystemContext* context) const { + return scoped_ptr<webkit_blob::FileStreamReader>(); +} + +scoped_ptr<FileStreamWriter> +PluginPrivateFileSystemBackend::CreateFileStreamWriter( + const FileSystemURL& url, + int64 offset, + FileSystemContext* context) const { + return scoped_ptr<FileStreamWriter>(); +} + +FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() { + return this; +} + +base::PlatformFileError +PluginPrivateFileSystemBackend::DeleteOriginDataOnFileThread( + FileSystemContext* context, + quota::QuotaManagerProxy* proxy, + const GURL& origin_url, + FileSystemType type) { + if (!CanHandleType(type)) + return base::PLATFORM_FILE_ERROR_SECURITY; + bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( + origin_url, std::string()); + if (result) + return base::PLATFORM_FILE_OK; + return base::PLATFORM_FILE_ERROR_FAILED; +} + +void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileThread( + FileSystemType type, + std::set<GURL>* origins) { + if (!CanHandleType(type)) + return; + scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( + obfuscated_file_util()->CreateOriginEnumerator()); + GURL origin; + while (!(origin = enumerator->Next()).is_empty()) + origins->insert(origin); +} + +void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileThread( + FileSystemType type, + const std::string& host, + std::set<GURL>* origins) { + if (!CanHandleType(type)) + return; + scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( + obfuscated_file_util()->CreateOriginEnumerator()); + GURL origin; + while (!(origin = enumerator->Next()).is_empty()) { + if (host == net::GetHostOrSpecFromURL(origin)) + origins->insert(origin); + } +} + +int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileThread( + FileSystemContext* context, + const GURL& origin_url, + FileSystemType type) { + // We don't track usage on this filesystem. + return 0; +} + +void PluginPrivateFileSystemBackend::AddFileUpdateObserver( + FileSystemType type, + FileUpdateObserver* observer, + base::SequencedTaskRunner* task_runner) {} + +void PluginPrivateFileSystemBackend::AddFileChangeObserver( + FileSystemType type, + FileChangeObserver* observer, + base::SequencedTaskRunner* task_runner) {} + +void PluginPrivateFileSystemBackend::AddFileAccessObserver( + FileSystemType type, + FileAccessObserver* observer, + base::SequencedTaskRunner* task_runner) {} + +const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers( + FileSystemType type) const { + return NULL; +} + +const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers( + FileSystemType type) const { + return NULL; +} + +const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers( + FileSystemType type) const { + return NULL; +} + +ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() { + return static_cast<ObfuscatedFileUtil*>( + static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util()); +} + +} // namespace fileapi diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.h b/webkit/browser/fileapi/plugin_private_file_system_backend.h new file mode 100644 index 0000000..b94d13a --- /dev/null +++ b/webkit/browser/fileapi/plugin_private_file_system_backend.h @@ -0,0 +1,136 @@ +// Copyright 2013 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_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ +#define WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ + +#include <set> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "webkit/browser/fileapi/file_system_backend.h" +#include "webkit/browser/fileapi/file_system_options.h" +#include "webkit/browser/fileapi/file_system_quota_util.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace quota { +class SpecialStoragePolicy; +} + +namespace fileapi { + +class ObfuscatedFileUtil; + +class WEBKIT_STORAGE_BROWSER_EXPORT PluginPrivateFileSystemBackend + : public FileSystemBackend, + public FileSystemQuotaUtil { + public: + class FileSystemIDToPluginMap; + + PluginPrivateFileSystemBackend( + base::SequencedTaskRunner* file_task_runner, + const base::FilePath& profile_path, + quota::SpecialStoragePolicy* special_storage_policy, + const FileSystemOptions& file_system_options); + virtual ~PluginPrivateFileSystemBackend(); + + // This must be used to open 'private' filesystem instead of regular + // OpenFileSystem. + // |plugin_id| must be an identifier string for per-plugin + // isolation, e.g. name, MIME type etc. + // NOTE: |plugin_id| must be sanitized ASCII string that doesn't + // include *any* dangerous character like '/'. + void OpenPrivateFileSystem( + const GURL& origin_url, + FileSystemType type, + const std::string& plugin_id, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback); + + // FileSystemBackend overrides. + virtual bool CanHandleType(FileSystemType type) const OVERRIDE; + virtual void Initialize(FileSystemContext* context) OVERRIDE; + virtual void OpenFileSystem( + const GURL& origin_url, + FileSystemType type, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; + virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; + virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( + FileSystemType type, + base::PlatformFileError* error_code) OVERRIDE; + virtual FileSystemOperation* CreateFileSystemOperation( + const FileSystemURL& url, + FileSystemContext* context, + base::PlatformFileError* error_code) const OVERRIDE; + virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader( + const FileSystemURL& url, + int64 offset, + const base::Time& expected_modification_time, + FileSystemContext* context) const OVERRIDE; + virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter( + const FileSystemURL& url, + int64 offset, + FileSystemContext* context) const OVERRIDE; + virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE; + + // FileSystemQuotaUtil overrides. + virtual base::PlatformFileError DeleteOriginDataOnFileThread( + FileSystemContext* context, + quota::QuotaManagerProxy* proxy, + const GURL& origin_url, + FileSystemType type) OVERRIDE; + virtual void GetOriginsForTypeOnFileThread( + FileSystemType type, + std::set<GURL>* origins) OVERRIDE; + virtual void GetOriginsForHostOnFileThread( + FileSystemType type, + const std::string& host, + std::set<GURL>* origins) OVERRIDE; + virtual int64 GetOriginUsageOnFileThread( + FileSystemContext* context, + const GURL& origin_url, + FileSystemType type) OVERRIDE; + virtual void AddFileUpdateObserver( + FileSystemType type, + FileUpdateObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual void AddFileChangeObserver( + FileSystemType type, + FileChangeObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual void AddFileAccessObserver( + FileSystemType type, + FileAccessObserver* observer, + base::SequencedTaskRunner* task_runner) OVERRIDE; + virtual const UpdateObserverList* GetUpdateObservers( + FileSystemType type) const OVERRIDE; + virtual const ChangeObserverList* GetChangeObservers( + FileSystemType type) const OVERRIDE; + virtual const AccessObserverList* GetAccessObservers( + FileSystemType type) const OVERRIDE; + + private: + friend class PluginPrivateFileSystemBackendTest; + + ObfuscatedFileUtil* obfuscated_file_util(); + const base::FilePath& base_path() const { return base_path_; } + + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + const FileSystemOptions file_system_options_; + const base::FilePath base_path_; + scoped_ptr<AsyncFileUtil> file_util_; + FileSystemIDToPluginMap* plugin_map_; // Owned by file_util_. + base::WeakPtrFactory<PluginPrivateFileSystemBackend> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(PluginPrivateFileSystemBackend); +}; + +} // namespace fileapi + +#endif // WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_ |