summaryrefslogtreecommitdiffstats
path: root/webkit/browser
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 12:09:03 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 12:09:03 +0000
commit1deb7321b0a90fb08acb64aa4e02ded84d203fcf (patch)
treee95bff6c7623aa96b5b1263e8effa5121f0522e5 /webkit/browser
parent8106aad9f908f8b473ecba072a2641d0afb7399a (diff)
downloadchromium_src-1deb7321b0a90fb08acb64aa4e02ded84d203fcf.zip
chromium_src-1deb7321b0a90fb08acb64aa4e02ded84d203fcf.tar.gz
chromium_src-1deb7321b0a90fb08acb64aa4e02ded84d203fcf.tar.bz2
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
Diffstat (limited to 'webkit/browser')
-rw-r--r--webkit/browser/chromeos/DEPS3
-rw-r--r--webkit/browser/chromeos/OWNERS2
-rw-r--r--webkit/browser/chromeos/fileapi/async_file_stream.h56
-rw-r--r--webkit/browser/chromeos/fileapi/cros_mount_point_provider.cc358
-rw-r--r--webkit/browser/chromeos/fileapi/cros_mount_point_provider.h144
-rw-r--r--webkit/browser/chromeos/fileapi/cros_mount_point_provider_unittest.cc304
-rw-r--r--webkit/browser/chromeos/fileapi/file_access_permissions.cc58
-rw-r--r--webkit/browser/chromeos/fileapi/file_access_permissions.h42
-rw-r--r--webkit/browser/chromeos/fileapi/file_access_permissions_unittest.cc67
-rw-r--r--webkit/browser/chromeos/fileapi/remote_file_stream_writer.cc119
-rw-r--r--webkit/browser/chromeos/fileapi/remote_file_stream_writer.h75
-rw-r--r--webkit/browser/chromeos/fileapi/remote_file_system_operation.cc321
-rw-r--r--webkit/browser/chromeos/fileapi/remote_file_system_operation.h135
-rw-r--r--webkit/browser/fileapi/file_system_context.cc2
-rw-r--r--webkit/browser/fileapi/webkit_browser_fileapi.gypi12
15 files changed, 1697 insertions, 1 deletions
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': [
{