From 1deb7321b0a90fb08acb64aa4e02ded84d203fcf Mon Sep 17 00:00:00 2001 From: "kinuko@chromium.org" <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> Date: Tue, 28 May 2013 12:09:03 +0000 Subject: Move webkit/chromeos into webkit/browser/chromeos As all of the code are browser-specific. BUG=239710 R=kinaba@chromium.org Review URL: https://codereview.chromium.org/16010006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202542 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/browser/chromeos/DEPS | 3 + webkit/browser/chromeos/OWNERS | 2 + .../browser/chromeos/fileapi/async_file_stream.h | 56 ++++ .../chromeos/fileapi/cros_mount_point_provider.cc | 358 +++++++++++++++++++++ .../chromeos/fileapi/cros_mount_point_provider.h | 144 +++++++++ .../fileapi/cros_mount_point_provider_unittest.cc | 304 +++++++++++++++++ .../chromeos/fileapi/file_access_permissions.cc | 58 ++++ .../chromeos/fileapi/file_access_permissions.h | 42 +++ .../fileapi/file_access_permissions_unittest.cc | 67 ++++ .../chromeos/fileapi/remote_file_stream_writer.cc | 119 +++++++ .../chromeos/fileapi/remote_file_stream_writer.h | 75 +++++ .../fileapi/remote_file_system_operation.cc | 321 ++++++++++++++++++ .../fileapi/remote_file_system_operation.h | 135 ++++++++ webkit/browser/fileapi/file_system_context.cc | 2 +- webkit/browser/fileapi/webkit_browser_fileapi.gypi | 12 + 15 files changed, 1697 insertions(+), 1 deletion(-) create mode 100644 webkit/browser/chromeos/DEPS create mode 100644 webkit/browser/chromeos/OWNERS create mode 100644 webkit/browser/chromeos/fileapi/async_file_stream.h create mode 100644 webkit/browser/chromeos/fileapi/cros_mount_point_provider.cc create mode 100644 webkit/browser/chromeos/fileapi/cros_mount_point_provider.h create mode 100644 webkit/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc create mode 100644 webkit/browser/chromeos/fileapi/file_access_permissions.cc create mode 100644 webkit/browser/chromeos/fileapi/file_access_permissions.h create mode 100644 webkit/browser/chromeos/fileapi/file_access_permissions_unittest.cc create mode 100644 webkit/browser/chromeos/fileapi/remote_file_stream_writer.cc create mode 100644 webkit/browser/chromeos/fileapi/remote_file_stream_writer.h create mode 100644 webkit/browser/chromeos/fileapi/remote_file_system_operation.cc create mode 100644 webkit/browser/chromeos/fileapi/remote_file_system_operation.h (limited to 'webkit/browser') diff --git a/webkit/browser/chromeos/DEPS b/webkit/browser/chromeos/DEPS new file mode 100644 index 0000000..79b8e8b --- /dev/null +++ b/webkit/browser/chromeos/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+chromeos", +] diff --git a/webkit/browser/chromeos/OWNERS b/webkit/browser/chromeos/OWNERS new file mode 100644 index 0000000..d4a1d71 --- /dev/null +++ b/webkit/browser/chromeos/OWNERS @@ -0,0 +1,2 @@ +satorux@chromium.org +zelidrag@chromium.org diff --git a/webkit/browser/chromeos/fileapi/async_file_stream.h b/webkit/browser/chromeos/fileapi/async_file_stream.h new file mode 100644 index 0000000..386101a --- /dev/null +++ b/webkit/browser/chromeos/fileapi/async_file_stream.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 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_CHROMEOS_FILEAPI_ASYNC_FILE_STREAM_H_ +#define WEBKIT_BROWSER_CHROMEOS_FILEAPI_ASYNC_FILE_STREAM_H_ + +#include "base/callback.h" +#include "base/platform_file.h" + +namespace fileapi { + +using base::PlatformFileError; + +// This class is used for implementing Open() in FileUtilAsync. This class +// is similar to net::FileStream, but supporting only the asynchronous +// operations and not necessarily relying on PlatformFile. +class AsyncFileStream { + public: + // Used for Read() and Write(). |result| is the return code of the + // operation, and |length| is the length of data read or written. + typedef base::Callback<void(PlatformFileError result, + int64 length)> ReadWriteCallback; + + // Used for Seek(). |result| is the return code of the operation. + typedef base::Callback<void(PlatformFileError)> SeekCallback; + + virtual ~AsyncFileStream() {}; + + // Reads data from the current stream position. Up to |length| bytes + // will be read from |buffer|. The memory pointed to by |buffer| must + // remain valid until the callback is called. On success, + // PLATFORM_FILE_OK is passed to |callback| with the number of bytes + // read. On failure, an error code is passed instead. + virtual void Read(char* buffer, + int64 length, + const ReadWriteCallback& callback) = 0; + + // Writes data at the current stream position. Up to |length| bytes will + // be written from |buffer|. The memory pointed to by |buffer| must + // remain valid until the callback is called. On success, + // PLATFORM_FILE_OK is passed to |callback| with the number of bytes + // written. On failure, an error code is passed instead. + virtual void Write(const char* buffer, + int64 length, + const ReadWriteCallback& callback) = 0; + + // Moves the stream position. On success, PLATFORM_FILE_OK is passed to + // |callback|. On error, an error code is passed instead. + virtual void Seek(int64 offset, + const SeekCallback& callback) = 0; +}; + +} // namespace fileapi + +#endif // WEBKIT_BROWSER_CHROMEOS_FILEAPI_ASYNC_FILE_STREAM_H_ diff --git a/webkit/browser/chromeos/fileapi/cros_mount_point_provider.cc b/webkit/browser/chromeos/fileapi/cros_mount_point_provider.cc new file mode 100644 index 0000000..c9270d5 --- /dev/null +++ b/webkit/browser/chromeos/fileapi/cros_mount_point_provider.cc @@ -0,0 +1,358 @@ +// 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. + +#include "webkit/browser/chromeos/fileapi/cros_mount_point_provider.h" + +#include "base/chromeos/chromeos_version.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/stringprintf.h" +#include "base/synchronization/lock.h" +#include "base/utf_string_conversions.h" +#include "chromeos/dbus/cros_disks_client.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebFileSystem.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" +#include "webkit/browser/chromeos/fileapi/file_access_permissions.h" +#include "webkit/browser/chromeos/fileapi/remote_file_stream_writer.h" +#include "webkit/browser/chromeos/fileapi/remote_file_system_operation.h" +#include "webkit/browser/fileapi/async_file_util_adapter.h" +#include "webkit/browser/fileapi/copy_or_move_file_validator.h" +#include "webkit/browser/fileapi/external_mount_points.h" +#include "webkit/browser/fileapi/file_system_context.h" +#include "webkit/browser/fileapi/file_system_file_stream_reader.h" +#include "webkit/browser/fileapi/file_system_operation_context.h" +#include "webkit/browser/fileapi/file_system_task_runners.h" +#include "webkit/browser/fileapi/file_system_url.h" +#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/isolated_file_util.h" +#include "webkit/browser/fileapi/local_file_stream_writer.h" +#include "webkit/browser/fileapi/local_file_system_operation.h" +#include "webkit/glue/webkit_glue.h" + +namespace { + +const char kChromeUIScheme[] = "chrome"; + +} // namespace + +namespace chromeos { + +// static +bool CrosMountPointProvider::CanHandleURL(const fileapi::FileSystemURL& url) { + if (!url.is_valid()) + return false; + return url.type() == fileapi::kFileSystemTypeNativeLocal || + url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal || + url.type() == fileapi::kFileSystemTypeDrive; +} + +CrosMountPointProvider::CrosMountPointProvider( + scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy, + scoped_refptr<fileapi::ExternalMountPoints> mount_points, + fileapi::ExternalMountPoints* system_mount_points) + : special_storage_policy_(special_storage_policy), + file_access_permissions_(new FileAccessPermissions()), + local_file_util_(new fileapi::AsyncFileUtilAdapter( + new fileapi::IsolatedFileUtil())), + mount_points_(mount_points), + system_mount_points_(system_mount_points) { + // Add default system mount points. + system_mount_points_->RegisterFileSystem( + "archive", + fileapi::kFileSystemTypeNativeLocal, + chromeos::CrosDisksClient::GetArchiveMountPoint()); + system_mount_points_->RegisterFileSystem( + "removable", + fileapi::kFileSystemTypeNativeLocal, + chromeos::CrosDisksClient::GetRemovableDiskMountPoint()); + system_mount_points_->RegisterFileSystem( + "oem", + fileapi::kFileSystemTypeRestrictedNativeLocal, + base::FilePath(FILE_PATH_LITERAL("/usr/share/oem"))); +} + +CrosMountPointProvider::~CrosMountPointProvider() { +} + +bool CrosMountPointProvider::CanHandleType(fileapi::FileSystemType type) const { + switch (type) { + case fileapi::kFileSystemTypeExternal: + case fileapi::kFileSystemTypeDrive: + case fileapi::kFileSystemTypeRestrictedNativeLocal: + case fileapi::kFileSystemTypeNativeLocal: + case fileapi::kFileSystemTypeNativeForPlatformApp: + return true; + default: + return false; + } +} + +void CrosMountPointProvider::ValidateFileSystemRoot( + const GURL& origin_url, + fileapi::FileSystemType type, + bool create, + const ValidateFileSystemCallback& callback) { + DCHECK(fileapi::IsolatedContext::IsIsolatedType(type)); + // Nothing to validate for external filesystem. + callback.Run(base::PLATFORM_FILE_OK); +} + +base::FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread( + const fileapi::FileSystemURL& url, + bool create) { + DCHECK(fileapi::IsolatedContext::IsIsolatedType(url.mount_type())); + if (!url.is_valid()) + return base::FilePath(); + + base::FilePath root_path; + std::string mount_name = url.filesystem_id(); + if (!mount_points_->GetRegisteredPath(mount_name, &root_path) && + !system_mount_points_->GetRegisteredPath(mount_name, &root_path)) { + return base::FilePath(); + } + + return root_path.DirName(); +} + +fileapi::FileSystemQuotaUtil* CrosMountPointProvider::GetQuotaUtil() { + // No quota support. + return NULL; +} + +void CrosMountPointProvider::DeleteFileSystem( + const GURL& origin_url, + fileapi::FileSystemType type, + fileapi::FileSystemContext* context, + const DeleteFileSystemCallback& callback) { + NOTREACHED(); + callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); +} + +bool CrosMountPointProvider::IsAccessAllowed( + const fileapi::FileSystemURL& url) const { + if (!url.is_valid()) + return false; + + // Permit access to mount points from internal WebUI. + const GURL& origin_url = url.origin(); + if (origin_url.SchemeIs(kChromeUIScheme)) + return true; + + // No extra check is needed for isolated file systems. + if (url.mount_type() == fileapi::kFileSystemTypeIsolated) + return true; + + if (!CanHandleURL(url)) + return false; + + std::string extension_id = origin_url.host(); + // Check first to make sure this extension has fileBrowserHander permissions. + if (!special_storage_policy_->IsFileHandler(extension_id)) + return false; + + return file_access_permissions_->HasAccessPermission(extension_id, + url.virtual_path()); +} + +void CrosMountPointProvider::GrantFullAccessToExtension( + const std::string& extension_id) { + DCHECK(special_storage_policy_->IsFileHandler(extension_id)); + if (!special_storage_policy_->IsFileHandler(extension_id)) + return; + + std::vector<fileapi::MountPoints::MountPointInfo> files; + mount_points_->AddMountPointInfosTo(&files); + system_mount_points_->AddMountPointInfosTo(&files); + + for (size_t i = 0; i < files.size(); ++i) { + file_access_permissions_->GrantAccessPermission( + extension_id, + base::FilePath::FromUTF8Unsafe(files[i].name)); + } +} + +void CrosMountPointProvider::GrantFileAccessToExtension( + const std::string& extension_id, const base::FilePath& virtual_path) { + // All we care about here is access from extensions for now. + DCHECK(special_storage_policy_->IsFileHandler(extension_id)); + if (!special_storage_policy_->IsFileHandler(extension_id)) + return; + + std::string id; + fileapi::FileSystemType type; + base::FilePath path; + if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &path) && + !system_mount_points_->CrackVirtualPath(virtual_path, + &id, &type, &path)) { + return; + } + + if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) { + LOG(ERROR) << "Can't grant access for restricted mount point"; + return; + } + + file_access_permissions_->GrantAccessPermission(extension_id, virtual_path); +} + +void CrosMountPointProvider::RevokeAccessForExtension( + const std::string& extension_id) { + file_access_permissions_->RevokePermissions(extension_id); +} + +std::vector<base::FilePath> CrosMountPointProvider::GetRootDirectories() const { + std::vector<fileapi::MountPoints::MountPointInfo> mount_points; + mount_points_->AddMountPointInfosTo(&mount_points); + system_mount_points_->AddMountPointInfosTo(&mount_points); + + std::vector<base::FilePath> root_dirs; + for (size_t i = 0; i < mount_points.size(); ++i) + root_dirs.push_back(mount_points[i].path); + return root_dirs; +} + +fileapi::FileSystemFileUtil* CrosMountPointProvider::GetFileUtil( + fileapi::FileSystemType type) { + DCHECK(type == fileapi::kFileSystemTypeNativeLocal || + type == fileapi::kFileSystemTypeRestrictedNativeLocal); + return local_file_util_->sync_file_util(); +} + +fileapi::AsyncFileUtil* CrosMountPointProvider::GetAsyncFileUtil( + fileapi::FileSystemType type) { + DCHECK(type == fileapi::kFileSystemTypeNativeLocal || + type == fileapi::kFileSystemTypeRestrictedNativeLocal); + return local_file_util_.get(); +} + +fileapi::CopyOrMoveFileValidatorFactory* +CrosMountPointProvider::GetCopyOrMoveFileValidatorFactory( + fileapi::FileSystemType type, base::PlatformFileError* error_code) { + DCHECK(error_code); + *error_code = base::PLATFORM_FILE_OK; + return NULL; +} + +void CrosMountPointProvider::InitializeCopyOrMoveFileValidatorFactory( + fileapi::FileSystemType type, + scoped_ptr<fileapi::CopyOrMoveFileValidatorFactory> factory) { + DCHECK(!factory); +} + +fileapi::FilePermissionPolicy CrosMountPointProvider::GetPermissionPolicy( + const fileapi::FileSystemURL& url, int permissions) const { + if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal && + (permissions & ~fileapi::kReadFilePermissions)) { + // Restricted file system is read-only. + return fileapi::FILE_PERMISSION_ALWAYS_DENY; + } + + if (!IsAccessAllowed(url)) + return fileapi::FILE_PERMISSION_ALWAYS_DENY; + + // Permit access to mount points from internal WebUI. + const GURL& origin_url = url.origin(); + if (origin_url.SchemeIs(kChromeUIScheme)) + return fileapi::FILE_PERMISSION_ALWAYS_ALLOW; + + if (url.mount_type() == fileapi::kFileSystemTypeIsolated) { + // Permissions in isolated filesystems should be examined with + // FileSystem permission. + return fileapi::FILE_PERMISSION_USE_FILESYSTEM_PERMISSION; + } + + // Also apply system's file permission by default. + return fileapi::FILE_PERMISSION_USE_FILE_PERMISSION; +} + +fileapi::FileSystemOperation* CrosMountPointProvider::CreateFileSystemOperation( + const fileapi::FileSystemURL& url, + fileapi::FileSystemContext* context, + base::PlatformFileError* error_code) const { + DCHECK(url.is_valid()); + + if (url.type() == fileapi::kFileSystemTypeDrive) { + fileapi::RemoteFileSystemProxyInterface* remote_proxy = + GetRemoteProxy(url.filesystem_id()); + if (!remote_proxy) { + *error_code = base::PLATFORM_FILE_ERROR_NOT_FOUND; + return NULL; + } + return new chromeos::RemoteFileSystemOperation(remote_proxy); + } + + DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal || + url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal); + scoped_ptr<fileapi::FileSystemOperationContext> operation_context( + new fileapi::FileSystemOperationContext(context)); + return new fileapi::LocalFileSystemOperation(context, + operation_context.Pass()); +} + +scoped_ptr<webkit_blob::FileStreamReader> +CrosMountPointProvider::CreateFileStreamReader( + const fileapi::FileSystemURL& url, + int64 offset, + const base::Time& expected_modification_time, + fileapi::FileSystemContext* context) const { + DCHECK(url.is_valid()); + + if (url.type() == fileapi::kFileSystemTypeDrive) { + fileapi::RemoteFileSystemProxyInterface* remote_proxy = + GetRemoteProxy(url.filesystem_id()); + if (!remote_proxy) + return scoped_ptr<webkit_blob::FileStreamReader>(); + return remote_proxy->CreateFileStreamReader( + context->task_runners()->file_task_runner(), + url, offset, expected_modification_time); + } + + return scoped_ptr<webkit_blob::FileStreamReader>( + new fileapi::FileSystemFileStreamReader( + context, url, offset, expected_modification_time)); +} + +scoped_ptr<fileapi::FileStreamWriter> +CrosMountPointProvider::CreateFileStreamWriter( + const fileapi::FileSystemURL& url, + int64 offset, + fileapi::FileSystemContext* context) const { + DCHECK(url.is_valid()); + + if (url.type() == fileapi::kFileSystemTypeDrive) { + fileapi::RemoteFileSystemProxyInterface* remote_proxy = + GetRemoteProxy(url.filesystem_id()); + if (!remote_proxy) + return scoped_ptr<fileapi::FileStreamWriter>(); + return scoped_ptr<fileapi::FileStreamWriter>( + new fileapi::RemoteFileStreamWriter(remote_proxy, url, offset)); + } + + if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal) + return scoped_ptr<fileapi::FileStreamWriter>(); + + DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal); + return scoped_ptr<fileapi::FileStreamWriter>( + new fileapi::LocalFileStreamWriter(url.path(), offset)); +} + +bool CrosMountPointProvider::GetVirtualPath( + const base::FilePath& filesystem_path, + base::FilePath* virtual_path) { + return mount_points_->GetVirtualPath(filesystem_path, virtual_path) || + system_mount_points_->GetVirtualPath(filesystem_path, virtual_path); +} + +fileapi::RemoteFileSystemProxyInterface* CrosMountPointProvider::GetRemoteProxy( + const std::string& mount_name) const { + fileapi::RemoteFileSystemProxyInterface* proxy = + mount_points_->GetRemoteFileSystemProxy(mount_name); + if (proxy) + return proxy; + return system_mount_points_->GetRemoteFileSystemProxy(mount_name); +} + +} // namespace chromeos diff --git a/webkit/browser/chromeos/fileapi/cros_mount_point_provider.h b/webkit/browser/chromeos/fileapi/cros_mount_point_provider.h new file mode 100644 index 0000000..6298078 --- /dev/null +++ b/webkit/browser/chromeos/fileapi/cros_mount_point_provider.h @@ -0,0 +1,144 @@ +// 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 WEBKIT_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_ +#define WEBKIT_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "webkit/browser/fileapi/file_system_mount_point_provider.h" +#include "webkit/common/fileapi/file_system_types.h" +#include "webkit/quota/special_storage_policy.h" +#include "webkit/storage/webkit_storage_export.h" + +namespace fileapi { +class AsyncFileUtilAdapter; +class CopyOrMoveFileValidatorFactory; +class ExternalMountPoints; +class FileSystemFileUtil; +class FileSystemURL; +class IsolatedContext; +} + +namespace chromeos { + +class FileAccessPermissions; + +// An interface to provide local filesystem paths. +class WEBKIT_STORAGE_EXPORT CrosMountPointProvider + : public fileapi::ExternalFileSystemMountPointProvider { + public: + using fileapi::FileSystemMountPointProvider::ValidateFileSystemCallback; + using fileapi::FileSystemMountPointProvider::DeleteFileSystemCallback; + + // CrosMountPointProvider will take an ownership of a |mount_points| + // reference. On the other hand, |system_mount_points| will be kept as a raw + // pointer and it should outlive CrosMountPointProvider instance. + CrosMountPointProvider( + scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy, + scoped_refptr<fileapi::ExternalMountPoints> mount_points, + fileapi::ExternalMountPoints* system_mount_points); + virtual ~CrosMountPointProvider(); + + // Returns true if CrosMountpointProvider can handle |url|, i.e. its + // file system type matches with what this provider supports. + // This could be called on any threads. + static bool CanHandleURL(const fileapi::FileSystemURL& url); + + // fileapi::FileSystemMountPointProvider overrides. + virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; + virtual void ValidateFileSystemRoot( + const GURL& origin_url, + fileapi::FileSystemType type, + bool create, + const ValidateFileSystemCallback& callback) OVERRIDE; + virtual base::FilePath GetFileSystemRootPathOnFileThread( + const fileapi::FileSystemURL& url, + bool create) OVERRIDE; + virtual fileapi::FileSystemFileUtil* GetFileUtil( + fileapi::FileSystemType type) OVERRIDE; + virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( + fileapi::FileSystemType type) OVERRIDE; + virtual fileapi::CopyOrMoveFileValidatorFactory* + GetCopyOrMoveFileValidatorFactory( + fileapi::FileSystemType type, + base::PlatformFileError* error_code) OVERRIDE; + virtual void InitializeCopyOrMoveFileValidatorFactory( + fileapi::FileSystemType type, + scoped_ptr<fileapi::CopyOrMoveFileValidatorFactory> factory) OVERRIDE; + virtual fileapi::FilePermissionPolicy GetPermissionPolicy( + const fileapi::FileSystemURL& url, + int permissions) const OVERRIDE; + virtual fileapi::FileSystemOperation* CreateFileSystemOperation( + const fileapi::FileSystemURL& url, + fileapi::FileSystemContext* context, + base::PlatformFileError* error_code) const OVERRIDE; + virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader( + const fileapi::FileSystemURL& path, + int64 offset, + const base::Time& expected_modification_time, + fileapi::FileSystemContext* context) const OVERRIDE; + virtual scoped_ptr<fileapi::FileStreamWriter> CreateFileStreamWriter( + const fileapi::FileSystemURL& url, + int64 offset, + fileapi::FileSystemContext* context) const OVERRIDE; + virtual fileapi::FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE; + virtual void DeleteFileSystem( + const GURL& origin_url, + fileapi::FileSystemType type, + fileapi::FileSystemContext* context, + const DeleteFileSystemCallback& callback) OVERRIDE; + + // fileapi::ExternalFileSystemMountPointProvider overrides. + virtual bool IsAccessAllowed(const fileapi::FileSystemURL& url) + const OVERRIDE; + virtual std::vector<base::FilePath> GetRootDirectories() const OVERRIDE; + virtual void GrantFullAccessToExtension( + const std::string& extension_id) OVERRIDE; + virtual void GrantFileAccessToExtension( + const std::string& extension_id, + const base::FilePath& virtual_path) OVERRIDE; + virtual void RevokeAccessForExtension( + const std::string& extension_id) OVERRIDE; + virtual bool GetVirtualPath(const base::FilePath& filesystem_path, + base::FilePath* virtual_path) OVERRIDE; + + private: + fileapi::RemoteFileSystemProxyInterface* GetRemoteProxy( + const std::string& mount_name) const; + + scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; + scoped_ptr<FileAccessPermissions> file_access_permissions_; + scoped_ptr<fileapi::AsyncFileUtilAdapter> local_file_util_; + + // Mount points specific to the owning context. + // + // Add/Remove MountPoints will affect only these mount points. + // + // It is legal to have mount points with the same name as in + // system_mount_points_. Also, mount point paths may overlap with mount point + // paths in system_mount_points_. In both cases mount points in + // |mount_points_| will have a priority. + // E.g. if |mount_points_| map 'foo1' to '/foo/foo1' and + // |file_system_mount_points_| map 'xxx' to '/foo/foo1/xxx', |GetVirtualPaths| + // will resolve '/foo/foo1/xxx/yyy' as 'foo1/xxx/yyy' (i.e. the mapping from + // |mount_points_| will be used). + scoped_refptr<fileapi::ExternalMountPoints> mount_points_; + + // Globally visible mount points. System MountPonts instance should outlive + // all CrosMountPointProvider instances, so raw pointer is safe. + fileapi::ExternalMountPoints* system_mount_points_; + + DISALLOW_COPY_AND_ASSIGN(CrosMountPointProvider); +}; + +} // namespace chromeos + +#endif // WEBKIT_BROWSER_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_ diff --git a/webkit/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc b/webkit/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc new file mode 100644 index 0000000..9eadd7c --- /dev/null +++ b/webkit/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc @@ -0,0 +1,304 @@ +// Copyright (c) 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/chromeos/fileapi/cros_mount_point_provider.h" + +#include <set> + +#include "base/files/file_path.h" +#include "chromeos/dbus/cros_disks_client.h" +#include "googleurl/src/url_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/external_mount_points.h" +#include "webkit/browser/fileapi/file_permission_policy.h" +#include "webkit/browser/fileapi/file_system_url.h" +#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/quota/mock_special_storage_policy.h" + +#define FPL(x) FILE_PATH_LITERAL(x) + +using fileapi::ExternalMountPoints; +using fileapi::FileSystemURL; + +namespace { + +FileSystemURL CreateFileSystemURL(const std::string& extension, + const char* path, + ExternalMountPoints* mount_points) { + return mount_points->CreateCrackedFileSystemURL( + GURL("chrome-extension://" + extension + "/"), + fileapi::kFileSystemTypeExternal, + base::FilePath::FromUTF8Unsafe(path)); +} + +TEST(CrosMountPointProviderTest, DefaultMountPoints) { + scoped_refptr<quota::SpecialStoragePolicy> storage_policy = + new quota::MockSpecialStoragePolicy(); + scoped_refptr<fileapi::ExternalMountPoints> mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + chromeos::CrosMountPointProvider provider( + storage_policy, + mount_points.get(), + fileapi::ExternalMountPoints::GetSystemInstance()); + std::vector<base::FilePath> root_dirs = provider.GetRootDirectories(); + std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end()); + + // By default there should be 3 mount points (in system mount points): + EXPECT_EQ(3u, root_dirs.size()); + EXPECT_TRUE(root_dirs_set.count( + chromeos::CrosDisksClient::GetRemovableDiskMountPoint())); + EXPECT_TRUE(root_dirs_set.count( + chromeos::CrosDisksClient::GetArchiveMountPoint())); + EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem")))); +} + +TEST(CrosMountPointProviderTest, GetRootDirectories) { + scoped_refptr<quota::SpecialStoragePolicy> storage_policy = + new quota::MockSpecialStoragePolicy(); + scoped_refptr<fileapi::ExternalMountPoints> mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + + scoped_refptr<fileapi::ExternalMountPoints> system_mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + + chromeos::CrosMountPointProvider provider( + storage_policy, + mount_points.get(), + system_mount_points.get()); + + const size_t initial_root_dirs_size = provider.GetRootDirectories().size(); + + // Register 'local' test mount points. + mount_points->RegisterFileSystem("c", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/a/b/c"))); + mount_points->RegisterFileSystem("d", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/b/c/d"))); + + // Register system test mount points. + system_mount_points->RegisterFileSystem("d", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/g/c/d"))); + system_mount_points->RegisterFileSystem("e", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/g/d/e"))); + + std::vector<base::FilePath> root_dirs = provider.GetRootDirectories(); + std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end()); + EXPECT_EQ(initial_root_dirs_size + 4, root_dirs.size()); + EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/a/b/c")))); + EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/b/c/d")))); + EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/c/d")))); + EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/d/e")))); +} + +TEST(CrosMountPointProviderTest, AccessPermissions) { + const int kPermission = fileapi::kReadFilePermissions; + + url_util::AddStandardScheme("chrome-extension"); + + scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy = + new quota::MockSpecialStoragePolicy(); + scoped_refptr<fileapi::ExternalMountPoints> mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + scoped_refptr<fileapi::ExternalMountPoints> system_mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + chromeos::CrosMountPointProvider provider( + storage_policy, + mount_points.get(), + system_mount_points.get()); + + std::string extension("ddammdhioacbehjngdmkjcjbnfginlla"); + + storage_policy->AddFileHandler(extension); + + // Initialize mount points. + ASSERT_TRUE(system_mount_points->RegisterFileSystem( + "system", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/g/system")))); + ASSERT_TRUE(mount_points->RegisterFileSystem( + "removable", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/media/removable")))); + ASSERT_TRUE(mount_points->RegisterFileSystem( + "oem", + fileapi::kFileSystemTypeRestrictedNativeLocal, + base::FilePath(FPL("/usr/share/oem")))); + + // Provider specific mount point access. + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "removable/foo", mount_points.get()), + kPermission)); + + provider.GrantFileAccessToExtension(extension, + base::FilePath(FPL("removable/foo"))); + EXPECT_EQ( + fileapi::FILE_PERMISSION_USE_FILE_PERMISSION, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "removable/foo", mount_points.get()), + kPermission)); + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "removable/foo1", mount_points.get()), + kPermission)); + + // System mount point access. + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "system/foo", + system_mount_points.get()), + kPermission)); + + provider.GrantFileAccessToExtension(extension, + base::FilePath(FPL("system/foo"))); + EXPECT_EQ( + fileapi::FILE_PERMISSION_USE_FILE_PERMISSION, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "system/foo", + system_mount_points.get()), + kPermission)); + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "system/foo1", + system_mount_points.get()), + kPermission)); + + // oem is restricted file system. + provider.GrantFileAccessToExtension( + extension, base::FilePath(FPL("oem/foo"))); + // The extension should not be able to access the file even if + // GrantFileAccessToExtension was called. + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "oem/foo", mount_points.get()), + kPermission)); + + provider.GrantFullAccessToExtension(extension); + // The extension should be able to access restricted file system after it was + // granted full access. + EXPECT_EQ( + fileapi::FILE_PERMISSION_USE_FILE_PERMISSION, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "oem/foo", mount_points.get()), + kPermission)); + // The extension which was granted full access should be able to access any + // path on current file systems. + EXPECT_EQ( + fileapi::FILE_PERMISSION_USE_FILE_PERMISSION, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "removable/foo1", mount_points.get()), + kPermission)); + EXPECT_EQ( + fileapi::FILE_PERMISSION_USE_FILE_PERMISSION, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "system/foo1", + system_mount_points.get()), + kPermission)); + + // The extension cannot access new mount points. + // TODO(tbarzic): This should probably be changed. + ASSERT_TRUE(mount_points->RegisterFileSystem( + "test", + fileapi::kFileSystemTypeNativeLocal, + base::FilePath(FPL("/foo/test")))); + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "test_/foo", mount_points.get()), + kPermission)); + + provider.RevokeAccessForExtension(extension); + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_DENY, + provider.GetPermissionPolicy( + CreateFileSystemURL(extension, "removable/foo", mount_points.get()), + kPermission)); + + fileapi::FileSystemURL internal_url = FileSystemURL::CreateForTest( + GURL("chrome://foo"), + fileapi::kFileSystemTypeExternal, + base::FilePath(FPL("removable/"))); + // Internal WebUI should have full access. + EXPECT_EQ( + fileapi::FILE_PERMISSION_ALWAYS_ALLOW, + provider.GetPermissionPolicy(internal_url, kPermission)); +} + +TEST(CrosMountPointProvider, GetVirtualPathConflictWithSystemPoints) { + scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy = + new quota::MockSpecialStoragePolicy(); + scoped_refptr<fileapi::ExternalMountPoints> mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + scoped_refptr<fileapi::ExternalMountPoints> system_mount_points( + fileapi::ExternalMountPoints::CreateRefCounted()); + chromeos::CrosMountPointProvider provider(storage_policy, + mount_points.get(), + system_mount_points.get()); + + const fileapi::FileSystemType type = fileapi::kFileSystemTypeNativeLocal; + + // Provider specific mount points. + ASSERT_TRUE( + mount_points->RegisterFileSystem("b", type, base::FilePath(FPL("/a/b")))); + ASSERT_TRUE( + mount_points->RegisterFileSystem("y", type, base::FilePath(FPL("/z/y")))); + ASSERT_TRUE( + mount_points->RegisterFileSystem("n", type, base::FilePath(FPL("/m/n")))); + + // System mount points + ASSERT_TRUE(system_mount_points->RegisterFileSystem( + "gb", type, base::FilePath(FPL("/a/b")))); + ASSERT_TRUE( + system_mount_points->RegisterFileSystem( + "gz", type, base::FilePath(FPL("/z")))); + ASSERT_TRUE(system_mount_points->RegisterFileSystem( + "gp", type, base::FilePath(FPL("/m/n/o/p")))); + + struct TestCase { + const base::FilePath::CharType* const local_path; + bool success; + const base::FilePath::CharType* const virtual_path; + }; + + const TestCase kTestCases[] = { + // Same paths in both mount points. + { FPL("/a/b/c/d"), true, FPL("b/c/d") }, + // System mount points path more specific. + { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") }, + // System mount points path less specific. + { FPL("/z/y/x"), true, FPL("y/x") }, + // Only system mount points path matches. + { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") }, + // No match. + { FPL("/foo/xxx"), false, FPL("") }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { + // Initialize virtual path with a value. + base::FilePath virtual_path(FPL("/mount")); + base::FilePath local_path(kTestCases[i].local_path); + EXPECT_EQ(kTestCases[i].success, + provider.GetVirtualPath(local_path, &virtual_path)) + << "Resolving " << kTestCases[i].local_path; + + // There are no guarantees for |virtual_path| value if |GetVirtualPath| + // fails. + if (!kTestCases[i].success) + continue; + + base::FilePath expected_virtual_path(kTestCases[i].virtual_path); + EXPECT_EQ(expected_virtual_path, virtual_path) + << "Resolving " << kTestCases[i].local_path; + } +} + +} // namespace diff --git a/webkit/browser/chromeos/fileapi/file_access_permissions.cc b/webkit/browser/chromeos/fileapi/file_access_permissions.cc new file mode 100644 index 0000000..db6d50a --- /dev/null +++ b/webkit/browser/chromeos/fileapi/file_access_permissions.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2011 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/chromeos/fileapi/file_access_permissions.h" + +#include "base/command_line.h" +#include "base/logging.h" + +namespace chromeos { + +FileAccessPermissions::FileAccessPermissions() {} + +FileAccessPermissions::~FileAccessPermissions() {} + + +void FileAccessPermissions::GrantAccessPermission( + const std::string& extension_id, const base::FilePath& path) { + base::AutoLock locker(lock_); + PathAccessMap::iterator path_map_iter = path_map_.find(extension_id); + if (path_map_iter == path_map_.end()) { + PathSet path_set; + path_set.insert(path); + path_map_.insert(PathAccessMap::value_type(extension_id, path_set)); + } else { + if (path_map_iter->second.find(path) != path_map_iter->second.end()) + return; + path_map_iter->second.insert(path); + } +} + +bool FileAccessPermissions::HasAccessPermission( + const std::string& extension_id, const base::FilePath& path) const { + base::AutoLock locker(lock_); + PathAccessMap::const_iterator path_map_iter = path_map_.find(extension_id); + if (path_map_iter == path_map_.end()) + return false; + + // Check this file and walk up its directory tree to find if this extension + // has access to it. + base::FilePath current_path = path.StripTrailingSeparators(); + base::FilePath last_path; + while (current_path != last_path) { + if (path_map_iter->second.find(current_path) != path_map_iter->second.end()) + return true; + last_path = current_path; + current_path = current_path.DirName(); + } + return false; +} + +void FileAccessPermissions::RevokePermissions( + const std::string& extension_id) { + base::AutoLock locker(lock_); + path_map_.erase(extension_id); +} + +} diff --git a/webkit/browser/chromeos/fileapi/file_access_permissions.h b/webkit/browser/chromeos/fileapi/file_access_permissions.h new file mode 100644 index 0000000..31cf195 --- /dev/null +++ b/webkit/browser/chromeos/fileapi/file_access_permissions.h @@ -0,0 +1,42 @@ +// Copyright (c) 2011 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_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ +#define WEBKIT_BROWSER_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ + +#include <map> +#include <set> +#include <string> + +#include "base/files/file_path.h" +#include "base/synchronization/lock.h" +#include "webkit/storage/webkit_storage_export.h" + +namespace chromeos { + +class WEBKIT_STORAGE_EXPORT FileAccessPermissions { + public: + FileAccessPermissions(); + virtual ~FileAccessPermissions(); + + // Grants |extension_id| access to |path|. + void GrantAccessPermission(const std::string& extension_id, + const base::FilePath& path); + // Checks id |extension_id| has permission to access to |path|. + bool HasAccessPermission(const std::string& extension_id, + const base::FilePath& path) const; + // Revokes all file permissions for |extension_id|. + void RevokePermissions(const std::string& extension_id); + + private: + typedef std::set<base::FilePath> PathSet; + typedef std::map<std::string, PathSet> PathAccessMap; + + mutable base::Lock lock_; // Synchronize all access to path_map_. + PathAccessMap path_map_; +}; + +} // namespace chromeos + +#endif // WEBKIT_BROWSER_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ diff --git a/webkit/browser/chromeos/fileapi/file_access_permissions_unittest.cc b/webkit/browser/chromeos/fileapi/file_access_permissions_unittest.cc new file mode 100644 index 0000000..3b6875d --- /dev/null +++ b/webkit/browser/chromeos/fileapi/file_access_permissions_unittest.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/chromeos/fileapi/file_access_permissions.h" + + +class FileAccessPermissionsTest : public testing::Test { +}; + +TEST_F(FileAccessPermissionsTest, FileAccessChecks) { +#if defined(OS_WIN) + base::FilePath good_dir(FILE_PATH_LITERAL("c:\\root\\dir")); + base::FilePath bad_dir(FILE_PATH_LITERAL("c:\\root")); + base::FilePath good_file(FILE_PATH_LITERAL("c:\\root\\dir\\good_file.txt")); + base::FilePath bad_file(FILE_PATH_LITERAL("c:\\root\\dir\\bad_file.txt")); +#elif defined(OS_POSIX) + base::FilePath good_dir(FILE_PATH_LITERAL("/root/dir")); + base::FilePath bad_dir(FILE_PATH_LITERAL("/root")); + base::FilePath good_file(FILE_PATH_LITERAL("/root/dir/good_file.txt")); + base::FilePath bad_file(FILE_PATH_LITERAL("/root/dir/bad_file.txt")); +#endif + std::string extension1("ddammdhioacbehjngdmkjcjbnfginlla"); + std::string extension2("jkhdjkhkhsdkfhsdkhrterwmtermeter"); + + chromeos::FileAccessPermissions permissions; + // By default extension have no access to any local file. + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); + + // After granting file access to the handler extension for a given file, it + // can only access that file an nothing else. + permissions.GrantAccessPermission(extension1, good_file); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); + + + // After granting file access to the handler extension for a given directory, + // it can access that directory and all files within it. + permissions.GrantAccessPermission(extension2, good_dir); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_TRUE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_TRUE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_TRUE(permissions.HasAccessPermission(extension2, bad_file)); + + // After revoking rights for extensions, they should not be able to access + // any file system element anymore. + permissions.RevokePermissions(extension1); + permissions.RevokePermissions(extension2); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); +} diff --git a/webkit/browser/chromeos/fileapi/remote_file_stream_writer.cc b/webkit/browser/chromeos/fileapi/remote_file_stream_writer.cc new file mode 100644 index 0000000..55b807e --- /dev/null +++ b/webkit/browser/chromeos/fileapi/remote_file_stream_writer.cc @@ -0,0 +1,119 @@ +// 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. + +#include "webkit/browser/chromeos/fileapi/remote_file_stream_writer.h" + +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "webkit/blob/local_file_stream_reader.h" +#include "webkit/blob/shareable_file_reference.h" +#include "webkit/browser/fileapi/local_file_stream_writer.h" +#include "webkit/browser/fileapi/remote_file_system_proxy.h" + +namespace fileapi { + +RemoteFileStreamWriter::RemoteFileStreamWriter( + const scoped_refptr<RemoteFileSystemProxyInterface>& remote_filesystem, + const FileSystemURL& url, + int64 offset) + : remote_filesystem_(remote_filesystem), + url_(url), + initial_offset_(offset), + has_pending_create_snapshot_(false), + weak_factory_(this) { +} + +RemoteFileStreamWriter::~RemoteFileStreamWriter() { +} + +int RemoteFileStreamWriter::Write(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) { + DCHECK(!has_pending_create_snapshot_); + DCHECK(pending_cancel_callback_.is_null()); + + if (!local_file_writer_) { + has_pending_create_snapshot_ = true; + // In this RemoteFileStreamWriter, we only create snapshot file and don't + // have explicit close operation. This is ok, because close is automatically + // triggered by a refcounted |file_ref_| passed to OnFileOpened, from the + // destructor of RemoteFileStreamWriter. + remote_filesystem_->CreateWritableSnapshotFile( + url_, + base::Bind(&RemoteFileStreamWriter::OnFileOpened, + weak_factory_.GetWeakPtr(), + make_scoped_refptr(buf), + buf_len, + callback)); + return net::ERR_IO_PENDING; + } + return local_file_writer_->Write(buf, buf_len, callback); +} + +void RemoteFileStreamWriter::OnFileOpened( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + base::PlatformFileError open_result, + const base::FilePath& local_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { + has_pending_create_snapshot_ = false; + if (!pending_cancel_callback_.is_null()) { + InvokePendingCancelCallback(net::OK); + return; + } + + if (open_result != base::PLATFORM_FILE_OK) { + callback.Run(net::PlatformFileErrorToNetError(open_result)); + return; + } + + // Hold the reference to the file. Releasing the reference notifies the file + // system about to close file. + file_ref_ = file_ref; + + DCHECK(!local_file_writer_.get()); + local_file_writer_.reset(new fileapi::LocalFileStreamWriter(local_path, + initial_offset_)); + int result = local_file_writer_->Write(buf, buf_len, callback); + if (result != net::ERR_IO_PENDING) + callback.Run(result); +} + +int RemoteFileStreamWriter::Cancel(const net::CompletionCallback& callback) { + DCHECK(!callback.is_null()); + DCHECK(pending_cancel_callback_.is_null()); + + // If file open operation is in-flight, wait for its completion and cancel + // further write operation in OnFileOpened. + if (has_pending_create_snapshot_) { + pending_cancel_callback_ = callback; + return net::ERR_IO_PENDING; + } + + // If LocalFileWriter is already created, just delegate the cancel to it. + if (local_file_writer_) { + pending_cancel_callback_ = callback; + return local_file_writer_->Cancel( + base::Bind(&RemoteFileStreamWriter::InvokePendingCancelCallback, + weak_factory_.GetWeakPtr())); + } + + // Write() is not called yet. + return net::ERR_UNEXPECTED; +} + +int RemoteFileStreamWriter::Flush(const net::CompletionCallback& callback) { + // For remote file writer, Flush() is a no-op. Synchronization to the remote + // server is not done until the file is closed. + return net::OK; +} + +void RemoteFileStreamWriter::InvokePendingCancelCallback(int result) { + net::CompletionCallback callback = pending_cancel_callback_; + pending_cancel_callback_.Reset(); + callback.Run(result); +} + +} // namespace gdata diff --git a/webkit/browser/chromeos/fileapi/remote_file_stream_writer.h b/webkit/browser/chromeos/fileapi/remote_file_stream_writer.h new file mode 100644 index 0000000..4799182 --- /dev/null +++ b/webkit/browser/chromeos/fileapi/remote_file_stream_writer.h @@ -0,0 +1,75 @@ +// 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 WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_ +#define WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_ + +#include "base/basictypes.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/platform_file.h" +#include "webkit/browser/fileapi/file_stream_writer.h" +#include "webkit/browser/fileapi/file_system_url.h" + +namespace net { +class IOBuffer; +} + +namespace webkit_blob { +class ShareableFileReference; +} + +namespace fileapi { + +class RemoteFileSystemProxyInterface; + +// FileStreamWriter interface for writing to a file on remote file system. +class RemoteFileStreamWriter : public fileapi::FileStreamWriter { + public: + // Creates a writer for a file on |remote_filesystem| with path url |url| + // (like "filesystem:chrome-extension://id/external/special/drive/...") that + // starts writing from |offset|. When invalid parameters are set, the first + // call to Write() method fails. + RemoteFileStreamWriter( + const scoped_refptr<RemoteFileSystemProxyInterface>& remote_filesystem, + const FileSystemURL& url, + int64 offset); + virtual ~RemoteFileStreamWriter(); + + // FileWriter override. + virtual int Write(net::IOBuffer* buf, int buf_len, + const net::CompletionCallback& callback) OVERRIDE; + virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; + virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; + + private: + // Callback function to do the continuation of the work of the first Write() + // call, which tries to open the local copy of the file before writing. + void OnFileOpened( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + base::PlatformFileError open_result, + const base::FilePath& local_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); + // Calls |pending_cancel_callback_|, assuming it is non-null. + void InvokePendingCancelCallback(int result); + + scoped_refptr<RemoteFileSystemProxyInterface> remote_filesystem_; + const FileSystemURL url_; + const int64 initial_offset_; + scoped_ptr<fileapi::FileStreamWriter> local_file_writer_; + scoped_refptr<webkit_blob::ShareableFileReference> file_ref_; + bool has_pending_create_snapshot_; + net::CompletionCallback pending_cancel_callback_; + + base::WeakPtrFactory<RemoteFileStreamWriter> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(RemoteFileStreamWriter); +}; + +} // namespace fileapi + +#endif // WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_STREAM_WRITER_H_ diff --git a/webkit/browser/chromeos/fileapi/remote_file_system_operation.cc b/webkit/browser/chromeos/fileapi/remote_file_system_operation.cc new file mode 100644 index 0000000..fcf129d --- /dev/null +++ b/webkit/browser/chromeos/fileapi/remote_file_system_operation.cc @@ -0,0 +1,321 @@ +// 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. + +#include "webkit/browser/chromeos/fileapi/remote_file_system_operation.h" + +#include "base/bind.h" +#include "base/platform_file.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "googleurl/src/gurl.h" +#include "net/url_request/url_request_context.h" +#include "webkit/browser/chromeos/fileapi/remote_file_stream_writer.h" +#include "webkit/browser/fileapi/file_system_url.h" +#include "webkit/browser/fileapi/file_writer_delegate.h" + +using fileapi::FileSystemURL; + +namespace chromeos { + +RemoteFileSystemOperation::RemoteFileSystemOperation( + scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy) + : remote_proxy_(remote_proxy), + pending_operation_(kOperationNone) { +} + +RemoteFileSystemOperation::~RemoteFileSystemOperation() { +} + +void RemoteFileSystemOperation::GetMetadata(const FileSystemURL& url, + const GetMetadataCallback& callback) { + DCHECK(SetPendingOperationType(kOperationGetMetadata)); + remote_proxy_->GetFileInfo(url, + base::Bind(&RemoteFileSystemOperation::DidGetMetadata, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::DirectoryExists(const FileSystemURL& url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationDirectoryExists)); + remote_proxy_->GetFileInfo(url, + base::Bind(&RemoteFileSystemOperation::DidDirectoryExists, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::FileExists(const FileSystemURL& url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationFileExists)); + remote_proxy_->GetFileInfo(url, + base::Bind(base::Bind(&RemoteFileSystemOperation::DidFileExists, + base::Owned(this), callback))); +} + +void RemoteFileSystemOperation::ReadDirectory(const FileSystemURL& url, + const ReadDirectoryCallback& callback) { + DCHECK(SetPendingOperationType(kOperationReadDirectory)); + remote_proxy_->ReadDirectory(url, + base::Bind(&RemoteFileSystemOperation::DidReadDirectory, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::Remove(const FileSystemURL& url, bool recursive, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationRemove)); + remote_proxy_->Remove(url, recursive, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + + +void RemoteFileSystemOperation::CreateDirectory( + const FileSystemURL& url, bool exclusive, bool recursive, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationCreateDirectory)); + remote_proxy_->CreateDirectory(url, exclusive, recursive, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::CreateFile(const FileSystemURL& url, + bool exclusive, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationCreateFile)); + remote_proxy_->CreateFile(url, exclusive, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::Copy(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationCopy)); + + remote_proxy_->Copy(src_url, dest_url, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::Move(const FileSystemURL& src_url, + const FileSystemURL& dest_url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationMove)); + + remote_proxy_->Move(src_url, dest_url, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::Write( + const net::URLRequestContext* url_request_context, + const FileSystemURL& url, + const GURL& blob_url, + int64 offset, + const WriteCallback& callback) { + DCHECK(SetPendingOperationType(kOperationWrite)); + DCHECK(write_callback_.is_null()); + + write_callback_ = callback; + file_writer_delegate_.reset( + new fileapi::FileWriterDelegate( + base::Bind(&RemoteFileSystemOperation::DidWrite, + // FileWriterDelegate is owned by |this|. So Unretained. + base::Unretained(this)), + scoped_ptr<fileapi::FileStreamWriter>( + new fileapi::RemoteFileStreamWriter(remote_proxy_, + url, + offset)))); + + scoped_ptr<net::URLRequest> blob_request(url_request_context->CreateRequest( + blob_url, file_writer_delegate_.get())); + + file_writer_delegate_->Start(blob_request.Pass()); +} + +void RemoteFileSystemOperation::Truncate(const FileSystemURL& url, + int64 length, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationTruncate)); + + remote_proxy_->Truncate(url, length, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::Cancel(const StatusCallback& cancel_callback) { + if (file_writer_delegate_) { + DCHECK_EQ(kOperationWrite, pending_operation_); + + // Writes are done without proxying through FileUtilProxy after the initial + // opening of the PlatformFile. All state changes are done on this thread, + // so we're guaranteed to be able to shut down atomically. + const bool delete_now = file_writer_delegate_->Cancel(); + + if (!write_callback_.is_null()) { + // Notify the failure status to the ongoing operation's callback. + write_callback_.Run(base::PLATFORM_FILE_ERROR_ABORT, 0, false); + } + cancel_callback.Run(base::PLATFORM_FILE_OK); + write_callback_.Reset(); + + if (delete_now) { + delete this; + return; + } + } else { + DCHECK_EQ(kOperationTruncate, pending_operation_); + // We're cancelling a truncate operation, but we can't actually stop it + // since it's been proxied to another thread. We need to save the + // cancel_callback so that when the truncate returns, it can see that it's + // been cancelled, report it, and report that the cancel has succeeded. + DCHECK(cancel_callback_.is_null()); + cancel_callback_ = cancel_callback; + } +} + +void RemoteFileSystemOperation::TouchFile(const FileSystemURL& url, + const base::Time& last_access_time, + const base::Time& last_modified_time, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationTouchFile)); + remote_proxy_->TouchFile( + url, + last_access_time, + last_modified_time, + base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void RemoteFileSystemOperation::OpenFile(const FileSystemURL& url, + int file_flags, + base::ProcessHandle peer_handle, + const OpenFileCallback& callback) { + DCHECK(SetPendingOperationType(kOperationOpenFile)); + remote_proxy_->OpenFile( + url, + file_flags, + peer_handle, + base::Bind(&RemoteFileSystemOperation::DidOpenFile, + base::Owned(this), url, callback)); +} + +fileapi::LocalFileSystemOperation* +RemoteFileSystemOperation::AsLocalFileSystemOperation() { + NOTIMPLEMENTED(); + return NULL; +} + +void RemoteFileSystemOperation::CreateSnapshotFile( + const FileSystemURL& url, + const SnapshotFileCallback& callback) { + DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile)); + remote_proxy_->CreateSnapshotFile( + url, + base::Bind(&RemoteFileSystemOperation::DidCreateSnapshotFile, + base::Owned(this), callback)); +} + +bool RemoteFileSystemOperation::SetPendingOperationType(OperationType type) { + if (pending_operation_ != kOperationNone) + return false; + pending_operation_ = type; + return true; +} + +void RemoteFileSystemOperation::DidDirectoryExists( + const StatusCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& unused) { + if (rv == base::PLATFORM_FILE_OK && !file_info.is_directory) + rv = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; + callback.Run(rv); +} + +void RemoteFileSystemOperation::DidFileExists( + const StatusCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& unused) { + if (rv == base::PLATFORM_FILE_OK && file_info.is_directory) + rv = base::PLATFORM_FILE_ERROR_NOT_A_FILE; + callback.Run(rv); +} + +void RemoteFileSystemOperation::DidGetMetadata( + const GetMetadataCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path) { + callback.Run(rv, file_info, platform_path); +} + +void RemoteFileSystemOperation::DidReadDirectory( + const ReadDirectoryCallback& callback, + base::PlatformFileError rv, + const std::vector<fileapi::DirectoryEntry>& entries, + bool has_more) { + callback.Run(rv, entries, has_more /* has_more */); +} + +void RemoteFileSystemOperation::DidWrite( + base::PlatformFileError rv, + int64 bytes, + FileWriterDelegate::WriteProgressStatus write_status) { + if (write_callback_.is_null()) { + // If cancelled, callback is already invoked and set to null in Cancel(). + // We must not call it twice. Just shut down this operation object. + delete this; + return; + } + + bool complete = (write_status != FileWriterDelegate::SUCCESS_IO_PENDING); + write_callback_.Run(rv, bytes, complete); + if (rv != base::PLATFORM_FILE_OK || complete) { + // Other Did*'s doesn't have "delete this", because it is automatic since + // they are base::Owned by the caller of the callback. For DidWrite, the + // owner is file_writer_delegate_ which itself is owned by this Operation + // object. Hence we need manual life time management here. + // TODO(kinaba): think about refactoring FileWriterDelegate to be self + // destructing, for avoiding the manual management. + delete this; + } +} + +void RemoteFileSystemOperation::DidFinishFileOperation( + const StatusCallback& callback, + base::PlatformFileError rv) { + if (!cancel_callback_.is_null()) { + DCHECK_EQ(kOperationTruncate, pending_operation_); + + callback.Run(base::PLATFORM_FILE_ERROR_ABORT); + cancel_callback_.Run(base::PLATFORM_FILE_OK); + cancel_callback_.Reset(); + } else { + callback.Run(rv); + } +} + +void RemoteFileSystemOperation::DidCreateSnapshotFile( + const SnapshotFileCallback& callback, + base::PlatformFileError result, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { + callback.Run(result, file_info, platform_path, file_ref); +} + +void RemoteFileSystemOperation::DidOpenFile( + const fileapi::FileSystemURL& url, + const OpenFileCallback& callback, + base::PlatformFileError result, + base::PlatformFile file, + base::ProcessHandle peer_handle) { + callback.Run( + result, file, + base::Bind(&fileapi::RemoteFileSystemProxyInterface::NotifyCloseFile, + remote_proxy_, url), + peer_handle); +} + +} // namespace chromeos diff --git a/webkit/browser/chromeos/fileapi/remote_file_system_operation.h b/webkit/browser/chromeos/fileapi/remote_file_system_operation.h new file mode 100644 index 0000000..e89fb71 --- /dev/null +++ b/webkit/browser/chromeos/fileapi/remote_file_system_operation.h @@ -0,0 +1,135 @@ +// 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 WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_ +#define WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_ + +#include "webkit/browser/fileapi/file_system_operation.h" +#include "webkit/browser/fileapi/file_writer_delegate.h" +#include "webkit/browser/fileapi/remote_file_system_proxy.h" + +namespace base { +class Value; +} + +namespace fileapi { +class FileWriterDelegate; +class LocalFileSystemOperation; +} + +namespace chromeos { + +// FileSystemOperation implementation for local file systems. +class RemoteFileSystemOperation : public fileapi::FileSystemOperation { + public: + typedef fileapi::FileWriterDelegate FileWriterDelegate; + virtual ~RemoteFileSystemOperation(); + + // FileSystemOperation overrides. + virtual void CreateFile(const fileapi::FileSystemURL& url, + bool exclusive, + const StatusCallback& callback) OVERRIDE; + virtual void CreateDirectory(const fileapi::FileSystemURL& url, + bool exclusive, + bool recursive, + const StatusCallback& callback) OVERRIDE; + virtual void Copy(const fileapi::FileSystemURL& src_url, + const fileapi::FileSystemURL& dest_url, + const StatusCallback& callback) OVERRIDE; + virtual void Move(const fileapi::FileSystemURL& src_url, + const fileapi::FileSystemURL& dest_url, + const StatusCallback& callback) OVERRIDE; + virtual void DirectoryExists(const fileapi::FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; + virtual void FileExists(const fileapi::FileSystemURL& url, + const StatusCallback& callback) OVERRIDE; + virtual void GetMetadata(const fileapi::FileSystemURL& url, + const GetMetadataCallback& callback) OVERRIDE; + virtual void ReadDirectory(const fileapi::FileSystemURL& url, + const ReadDirectoryCallback& callback) OVERRIDE; + virtual void Remove(const fileapi::FileSystemURL& url, bool recursive, + const StatusCallback& callback) OVERRIDE; + virtual void Write(const net::URLRequestContext* url_request_context, + const fileapi::FileSystemURL& url, + const GURL& blob_url, + int64 offset, + const WriteCallback& callback) OVERRIDE; + virtual void Truncate(const fileapi::FileSystemURL& url, int64 length, + const StatusCallback& callback) OVERRIDE; + virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE; + virtual void TouchFile(const fileapi::FileSystemURL& url, + const base::Time& last_access_time, + const base::Time& last_modified_time, + const StatusCallback& callback) OVERRIDE; + virtual void OpenFile( + const fileapi::FileSystemURL& url, + int file_flags, + base::ProcessHandle peer_handle, + const OpenFileCallback& callback) OVERRIDE; + virtual fileapi::LocalFileSystemOperation* + AsLocalFileSystemOperation() OVERRIDE; + virtual void CreateSnapshotFile( + const fileapi::FileSystemURL& url, + const SnapshotFileCallback& callback) OVERRIDE; + + private: + friend class CrosMountPointProvider; + + RemoteFileSystemOperation( + scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy); + + // Used only for internal assertions. + // Returns false if there's another inflight pending operation. + bool SetPendingOperationType(OperationType type); + + // Generic callback that translates platform errors to WebKit error codes. + void DidDirectoryExists(const StatusCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& unused); + void DidFileExists(const StatusCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& unused); + void DidGetMetadata(const GetMetadataCallback& callback, + base::PlatformFileError rv, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path); + void DidReadDirectory(const ReadDirectoryCallback& callback, + base::PlatformFileError rv, + const std::vector<fileapi::DirectoryEntry>& entries, + bool has_more); + void DidWrite(base::PlatformFileError result, + int64 bytes, + FileWriterDelegate::WriteProgressStatus write_status); + void DidFinishFileOperation(const StatusCallback& callback, + base::PlatformFileError rv); + void DidCreateSnapshotFile( + const SnapshotFileCallback& callback, + base::PlatformFileError result, + const base::PlatformFileInfo& file_info, + const base::FilePath& platform_path, + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref); + void DidOpenFile( + const fileapi::FileSystemURL& url, + const OpenFileCallback& callback, + base::PlatformFileError result, + base::PlatformFile file, + base::ProcessHandle peer_handle); + + + scoped_refptr<fileapi::RemoteFileSystemProxyInterface> remote_proxy_; + // A flag to make sure we call operation only once per instance. + OperationType pending_operation_; + scoped_ptr<fileapi::FileWriterDelegate> file_writer_delegate_; + + WriteCallback write_callback_; + StatusCallback cancel_callback_; + + DISALLOW_COPY_AND_ASSIGN(RemoteFileSystemOperation); +}; + +} // namespace chromeos + +#endif // WEBKIT_BROWSER_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_ diff --git a/webkit/browser/fileapi/file_system_context.cc b/webkit/browser/fileapi/file_system_context.cc index a25f050..977db2d 100644 --- a/webkit/browser/fileapi/file_system_context.cc +++ b/webkit/browser/fileapi/file_system_context.cc @@ -31,7 +31,7 @@ #include "webkit/quota/special_storage_policy.h" #if defined(OS_CHROMEOS) -#include "webkit/chromeos/fileapi/cros_mount_point_provider.h" +#include "webkit/browser/chromeos/fileapi/cros_mount_point_provider.h" #endif using quota::QuotaClient; diff --git a/webkit/browser/fileapi/webkit_browser_fileapi.gypi b/webkit/browser/fileapi/webkit_browser_fileapi.gypi index ecea36e..7502072 100644 --- a/webkit/browser/fileapi/webkit_browser_fileapi.gypi +++ b/webkit/browser/fileapi/webkit_browser_fileapi.gypi @@ -111,6 +111,18 @@ '../browser/fileapi/upload_file_system_file_element_reader.cc', '../browser/fileapi/upload_file_system_file_element_reader.h', ], + 'webkit_browser_fileapi_chromeos_sources': [ + '../browser/chromeos/fileapi/async_file_stream.h', + '../browser/chromeos/fileapi/cros_mount_point_provider.cc', + '../browser/chromeos/fileapi/cros_mount_point_provider.h', + '../browser/chromeos/fileapi/file_access_permissions.cc', + '../browser/chromeos/fileapi/file_access_permissions.h', + '../browser/chromeos/fileapi/file_util_async.h', + '../browser/chromeos/fileapi/remote_file_system_operation.cc', + '../browser/chromeos/fileapi/remote_file_system_operation.h', + '../browser/chromeos/fileapi/remote_file_stream_writer.cc', + '../browser/chromeos/fileapi/remote_file_stream_writer.h', + ], }, 'targets': [ { -- cgit v1.1