summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi
diff options
context:
space:
mode:
authorericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:49:40 +0000
committerericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:49:40 +0000
commit073a04f0599beb27670d8a6738fcbbc22fa97bcf (patch)
treed7393b3cd3463dbfaf4bbdc02fdd0a4de0c83995 /webkit/fileapi
parent6bcd5f36cd94649887eff0c87df4f4496001984a (diff)
downloadchromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.zip
chromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.tar.gz
chromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.tar.bz2
Stop returning the true root path of each filesystem from openFileSystem.
Instead, return the FileSystem URI of the root. This will make it easier to swap in different filesystem implementations. BUG=71635 TEST=Just a couple in FileSystemUtilTests, but a bunch of existing ones [this doesn't add much new functionality]. Review URL: http://codereview.chromium.org/6603034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79228 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r--webkit/fileapi/file_system_context.cc9
-rw-r--r--webkit/fileapi/file_system_context.h2
-rw-r--r--webkit/fileapi/file_system_file_util.cc1
-rw-r--r--webkit/fileapi/file_system_mount_point_provider.h48
-rw-r--r--webkit/fileapi/file_system_operation.cc235
-rw-r--r--webkit/fileapi/file_system_operation.h33
-rw-r--r--webkit/fileapi/file_system_operation_context.cc21
-rw-r--r--webkit/fileapi/file_system_operation_context.h51
-rw-r--r--webkit/fileapi/file_system_operation_unittest.cc11
-rw-r--r--webkit/fileapi/file_system_path_manager.cc373
-rw-r--r--webkit/fileapi/file_system_path_manager.h78
-rw-r--r--webkit/fileapi/file_system_path_manager_unittest.cc126
-rw-r--r--webkit/fileapi/file_system_usage_tracker.cc7
-rw-r--r--webkit/fileapi/file_system_usage_tracker.h9
-rw-r--r--webkit/fileapi/file_system_usage_tracker_unittest.cc8
-rw-r--r--webkit/fileapi/file_system_util.cc80
-rw-r--r--webkit/fileapi/file_system_util.h4
-rw-r--r--webkit/fileapi/file_system_util_unittest.cc14
-rw-r--r--webkit/fileapi/local_file_system_file_util.cc178
-rw-r--r--webkit/fileapi/local_file_system_file_util.h112
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.cc312
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.h120
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider_unittest.cc100
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi7
24 files changed, 1410 insertions, 529 deletions
diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc
index 71e5ed2..b5c1308 100644
--- a/webkit/fileapi/file_system_context.cc
+++ b/webkit/fileapi/file_system_context.cc
@@ -9,6 +9,7 @@
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_path_manager.h"
#include "webkit/fileapi/file_system_usage_tracker.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
namespace fileapi {
@@ -50,8 +51,8 @@ void FileSystemContext::DeleteDataForOriginOnFileThread(
DCHECK(file_message_loop_->BelongsToCurrentThread());
std::string origin_identifier =
- FileSystemPathManager::GetOriginIdentifierFromURL(origin_url);
- FilePath path_for_origin = path_manager_->base_path().AppendASCII(
+ SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url);
+ FilePath path_for_origin = sandbox_provider()->base_path().AppendASCII(
origin_identifier);
file_util::Delete(path_for_origin, true /* recursive */);
@@ -65,4 +66,8 @@ void FileSystemContext::DeleteOnCorrectThread() const {
delete this;
}
+SandboxMountPointProvider* FileSystemContext::sandbox_provider() const {
+ return path_manager_->sandbox_provider();
+}
+
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_context.h b/webkit/fileapi/file_system_context.h
index 0da1d99..16e3551 100644
--- a/webkit/fileapi/file_system_context.h
+++ b/webkit/fileapi/file_system_context.h
@@ -25,6 +25,7 @@ namespace fileapi {
class FileSystemContext;
class FileSystemPathManager;
class FileSystemUsageTracker;
+class SandboxMountPointProvider;
struct DefaultContextDeleter;
@@ -54,6 +55,7 @@ class FileSystemContext
private:
friend struct DefaultContextDeleter;
void DeleteOnCorrectThread() const;
+ SandboxMountPointProvider* sandbox_provider() const;
scoped_refptr<base::MessageLoopProxy> file_message_loop_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_;
diff --git a/webkit/fileapi/file_system_file_util.cc b/webkit/fileapi/file_system_file_util.cc
index 8c11c48..10af22f 100644
--- a/webkit/fileapi/file_system_file_util.cc
+++ b/webkit/fileapi/file_system_file_util.cc
@@ -66,6 +66,7 @@ PlatformFileError FileSystemFileUtil::GetFileInfo(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
if (!file_util::GetFileInfo(file_path, file_info))
return base::PLATFORM_FILE_ERROR_FAILED;
+ file_info->path = file_path;
return base::PLATFORM_FILE_OK;
}
diff --git a/webkit/fileapi/file_system_mount_point_provider.h b/webkit/fileapi/file_system_mount_point_provider.h
new file mode 100644
index 0000000..3136636
--- /dev/null
+++ b/webkit/fileapi/file_system_mount_point_provider.h
@@ -0,0 +1,48 @@
+// 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_FILEAPI_FILE_SYSTEM_MOUNT_POINT_PROVIDER_H_
+#define WEBKIT_FILEAPI_FILE_SYSTEM_MOUNT_POINT_PROVIDER_H_
+
+#include "base/file_path.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_types.h"
+
+namespace fileapi {
+
+// An interface to provide local filesystem paths.
+
+class FileSystemMountPointProvider {
+ public:
+ virtual ~FileSystemMountPointProvider() {}
+
+ // Checks if mount point access is allowed from |origin_url|.
+ virtual bool IsAccessAllowed(const GURL& origin_url) = 0;
+
+ // Retrieves the root path for the given |origin_url| and |type|, and
+ // calls the given |callback| with the root path and name.
+ // If |create| is true this also creates the directory if it doesn't exist.
+ virtual void GetFileSystemRootPath(
+ const GURL& origin_url,
+ FileSystemType type,
+ bool create,
+ FileSystemPathManager::GetRootPathCallback* callback) = 0;
+
+ // Like GetFileSystemRootPath, but synchronous, and can be called only while
+ // running on the file thread.
+ virtual FilePath GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ FileSystemType type,
+ bool create) = 0;
+
+ // Checks if a given |name| contains any restricted names/chars in it.
+ // Callable on any thread.
+ virtual bool IsRestrictedFileName(const FilePath& filename) const = 0;
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_FILE_SYSTEM_MOUNT_POINT_PROVIDER_H_
+
diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc
index 0b800ba..5de0c64 100644
--- a/webkit/fileapi/file_system_operation.cc
+++ b/webkit/fileapi/file_system_operation.cc
@@ -11,18 +11,22 @@
#include "webkit/fileapi/file_system_file_util_proxy.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/file_writer_delegate.h"
+#include "webkit/fileapi/local_file_system_file_util.h"
namespace fileapi {
FileSystemOperation::FileSystemOperation(
FileSystemCallbackDispatcher* dispatcher,
scoped_refptr<base::MessageLoopProxy> proxy,
- FileSystemContext* file_system_context)
+ FileSystemContext* file_system_context,
+ FileSystemFileUtil* file_system_file_util)
: proxy_(proxy),
dispatcher_(dispatcher),
- file_system_context_(file_system_context),
- file_system_operation_context_(FileSystemFileUtil::GetInstance()),
+ file_system_operation_context_(file_system_context,
+ file_system_file_util ? file_system_file_util :
+ LocalFileSystemFileUtil::GetInstance()),
callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(dispatcher);
#ifndef NDEBUG
@@ -45,8 +49,16 @@ void FileSystemOperation::OpenFileSystem(
kOperationOpenFileSystem);
#endif
- DCHECK(file_system_context_.get());
- file_system_context_->path_manager()->GetFileSystemRootPath(
+ DCHECK(file_system_context());
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
+ // TODO(ericu): We don't really need to make this call if !create.
+ // Also, in the future we won't need it either way, as long as we do all
+ // permission+quota checks beforehand. We only need it now because we have to
+ // create an unpredictable directory name. Without that, we could lazily
+ // create the root later on the first filesystem write operation, and just
+ // return GetFileSystemRootURI() here.
+ file_system_context()->path_manager()->GetFileSystemRootPath(
origin_url, type, create,
callback_factory_.NewCallback(&FileSystemOperation::DidGetRootPath));
}
@@ -57,14 +69,19 @@ void FileSystemOperation::CreateFile(const FilePath& path,
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationCreateFile;
#endif
-
- if (!VerifyFileSystemPathForWrite(path, true /* create */)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForWrite(
+ path, true /* create */, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::EnsureFileExists(
file_system_operation_context_,
- proxy_, path, callback_factory_.NewCallback(
+ proxy_, virtual_path, callback_factory_.NewCallback(
exclusive ? &FileSystemOperation::DidEnsureFileExistsExclusive
: &FileSystemOperation::DidEnsureFileExistsNonExclusive));
}
@@ -76,14 +93,20 @@ void FileSystemOperation::CreateDirectory(const FilePath& path,
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationCreateDirectory;
#endif
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
- if (!VerifyFileSystemPathForWrite(path, true /* create */)) {
+ if (!VerifyFileSystemPathForWrite(
+ path, true /* create */, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::CreateDirectory(
file_system_operation_context_,
- proxy_, path, exclusive, recursive, callback_factory_.NewCallback(
+ proxy_, virtual_path, exclusive, recursive, callback_factory_.NewCallback(
&FileSystemOperation::DidFinishFileOperation));
}
@@ -93,16 +116,37 @@ void FileSystemOperation::Copy(const FilePath& src_path,
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationCopy;
#endif
-
- if (!VerifyFileSystemPathForRead(src_path) ||
- !VerifyFileSystemPathForWrite(dest_path, true /* create */)) {
+ FilePath virtual_path_0;
+ FilePath virtual_path_1;
+ GURL src_origin_url;
+ GURL dest_origin_url;
+ FileSystemType src_type;
+ FileSystemType dest_type;
+
+ if (!VerifyFileSystemPathForRead(src_path, &src_origin_url, &src_type,
+ &virtual_path_0) ||
+ !VerifyFileSystemPathForWrite(dest_path, true /* create */,
+ &dest_origin_url, &dest_type, &virtual_path_1)) {
delete this;
return;
}
+ if (src_origin_url.GetOrigin() != dest_origin_url.GetOrigin()) {
+ // TODO(ericu): We don't yet support copying across filesystem types, from
+ // extension to sandbox, etc. From temporary to persistent works, though.
+ // Since the sandbox code isn't in yet, I'm not sure exactly what check
+ // belongs here, but there's also no danger yet.
+ delete this;
+ return;
+ }
+ file_system_operation_context_.set_src_origin_url(src_origin_url);
+ file_system_operation_context_.set_dest_origin_url(dest_origin_url);
+ file_system_operation_context_.set_src_type(src_type);
+ file_system_operation_context_.set_dest_type(dest_type);
FileSystemFileUtilProxy::Copy(
file_system_operation_context_,
- proxy_, src_path, dest_path, callback_factory_.NewCallback(
- &FileSystemOperation::DidFinishFileOperation));
+ proxy_, virtual_path_0, virtual_path_1,
+ callback_factory_.NewCallback(
+ &FileSystemOperation::DidFinishFileOperation));
}
void FileSystemOperation::Move(const FilePath& src_path,
@@ -111,16 +155,35 @@ void FileSystemOperation::Move(const FilePath& src_path,
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationMove;
#endif
-
- if (!VerifyFileSystemPathForRead(src_path) ||
- !VerifyFileSystemPathForWrite(dest_path, true /* create */)) {
+ FilePath virtual_path_0;
+ FilePath virtual_path_1;
+ GURL src_origin_url;
+ GURL dest_origin_url;
+ FileSystemType src_type;
+ FileSystemType dest_type;
+
+ if (!VerifyFileSystemPathForRead(src_path, &src_origin_url, &src_type,
+ &virtual_path_0) ||
+ !VerifyFileSystemPathForWrite(dest_path, true /* create */,
+ &dest_origin_url, &dest_type, &virtual_path_1)) {
+ delete this;
+ return;
+ }
+ if (src_origin_url.GetOrigin() != dest_origin_url.GetOrigin()) {
+ // TODO(ericu): We don't yet support moving across filesystem types, from
+ // extension to sandbox, etc. From temporary to persistent works, though.
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(src_origin_url);
+ file_system_operation_context_.set_dest_origin_url(dest_origin_url);
+ file_system_operation_context_.set_src_type(src_type);
+ file_system_operation_context_.set_dest_type(dest_type);
FileSystemFileUtilProxy::Move(
file_system_operation_context_,
- proxy_, src_path, dest_path, callback_factory_.NewCallback(
- &FileSystemOperation::DidFinishFileOperation));
+ proxy_, virtual_path_0, virtual_path_1,
+ callback_factory_.NewCallback(
+ &FileSystemOperation::DidFinishFileOperation));
}
void FileSystemOperation::DirectoryExists(const FilePath& path) {
@@ -129,13 +192,18 @@ void FileSystemOperation::DirectoryExists(const FilePath& path) {
pending_operation_ = kOperationDirectoryExists;
#endif
- if (!VerifyFileSystemPathForRead(path)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForRead(path, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::GetFileInfo(
file_system_operation_context_,
- proxy_, path, callback_factory_.NewCallback(
+ proxy_, virtual_path, callback_factory_.NewCallback(
&FileSystemOperation::DidDirectoryExists));
}
@@ -145,13 +213,18 @@ void FileSystemOperation::FileExists(const FilePath& path) {
pending_operation_ = kOperationFileExists;
#endif
- if (!VerifyFileSystemPathForRead(path)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForRead(path, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::GetFileInfo(
file_system_operation_context_,
- proxy_, path, callback_factory_.NewCallback(
+ proxy_, virtual_path, callback_factory_.NewCallback(
&FileSystemOperation::DidFileExists));
}
@@ -161,13 +234,18 @@ void FileSystemOperation::GetMetadata(const FilePath& path) {
pending_operation_ = kOperationGetMetadata;
#endif
- if (!VerifyFileSystemPathForRead(path)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForRead(path, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::GetFileInfo(
file_system_operation_context_,
- proxy_, path, callback_factory_.NewCallback(
+ proxy_, virtual_path, callback_factory_.NewCallback(
&FileSystemOperation::DidGetMetadata));
}
@@ -177,13 +255,18 @@ void FileSystemOperation::ReadDirectory(const FilePath& path) {
pending_operation_ = kOperationReadDirectory;
#endif
- if (!VerifyFileSystemPathForRead(path)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForRead(path, &origin_url, &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::ReadDirectory(
file_system_operation_context_,
- proxy_, path, callback_factory_.NewCallback(
+ proxy_, virtual_path, callback_factory_.NewCallback(
&FileSystemOperation::DidReadDirectory));
}
@@ -193,13 +276,19 @@ void FileSystemOperation::Remove(const FilePath& path, bool recursive) {
pending_operation_ = kOperationRemove;
#endif
- if (!VerifyFileSystemPathForWrite(path, false /* create */)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForWrite(path, false /* create */, &origin_url,
+ &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::Delete(
file_system_operation_context_,
- proxy_, path, recursive, callback_factory_.NewCallback(
+ proxy_, virtual_path, recursive, callback_factory_.NewCallback(
&FileSystemOperation::DidFinishFileOperation));
}
@@ -212,10 +301,16 @@ void FileSystemOperation::Write(
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationWrite;
#endif
- if (!VerifyFileSystemPathForWrite(path, true /* create */)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForWrite(path, true /* create */, &origin_url,
+ &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
DCHECK(blob_url.is_valid());
file_writer_delegate_.reset(new FileWriterDelegate(this, offset));
blob_request_.reset(
@@ -224,7 +319,7 @@ void FileSystemOperation::Write(
FileSystemFileUtilProxy::CreateOrOpen(
file_system_operation_context_,
proxy_,
- path,
+ virtual_path,
base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_ASYNC,
callback_factory_.NewCallback(
@@ -236,13 +331,19 @@ void FileSystemOperation::Truncate(const FilePath& path, int64 length) {
DCHECK(kOperationNone == pending_operation_);
pending_operation_ = kOperationTruncate;
#endif
- if (!VerifyFileSystemPathForWrite(path, false /* create */)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForWrite(path, false /* create */, &origin_url,
+ &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::Truncate(
file_system_operation_context_,
- proxy_, path, length, callback_factory_.NewCallback(
+ proxy_, virtual_path, length, callback_factory_.NewCallback(
&FileSystemOperation::DidFinishFileOperation));
}
@@ -254,13 +355,19 @@ void FileSystemOperation::TouchFile(const FilePath& path,
pending_operation_ = kOperationTouchFile;
#endif
- if (!VerifyFileSystemPathForWrite(path, true /* create */)) {
+ FilePath virtual_path;
+ GURL origin_url;
+ FileSystemType type;
+ if (!VerifyFileSystemPathForWrite(path, true /* create */, &origin_url,
+ &type, &virtual_path)) {
delete this;
return;
}
+ file_system_operation_context_.set_src_origin_url(origin_url);
+ file_system_operation_context_.set_src_type(type);
FileSystemFileUtilProxy::Touch(
file_system_operation_context_,
- proxy_, path, last_access_time, last_modified_time,
+ proxy_, virtual_path, last_access_time, last_modified_time,
callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile));
}
@@ -300,7 +407,16 @@ void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation_ptr) {
void FileSystemOperation::DidGetRootPath(
bool success, const FilePath& path, const std::string& name) {
DCHECK(success || path.empty());
- dispatcher_->DidOpenFileSystem(name, path);
+ FilePath result;
+ // We ignore the path, and return a URL instead. The point was just to verify
+ // that we could create/find the path.
+ if (success) {
+ GURL root_url = GetFileSystemRootURI(
+ file_system_operation_context_.src_origin_url(),
+ file_system_operation_context_.src_type());
+ result = FilePath().AppendASCII(root_url.spec());
+ }
+ dispatcher_->DidOpenFileSystem(name, result);
delete this;
}
@@ -416,15 +532,21 @@ void FileSystemOperation::OnFileOpenedForWrite(
}
bool FileSystemOperation::VerifyFileSystemPathForRead(
- const FilePath& path) {
- // If we have no context, we just allow any operations.
- if (!file_system_context_.get())
+ const FilePath& path, GURL* origin_url, FileSystemType* type,
+ FilePath* virtual_path) {
+
+ // If we have no context, we just allow any operations, for testing.
+ // TODO(ericu): Revisit this hack for security.
+ if (!file_system_context()) {
+ *virtual_path = path;
+ *type = file_system_operation_context_.src_type();
return true;
+ }
// We may want do more checks, but for now it just checks if the given
// |path| is under the valid FileSystem root path for this host context.
- if (!file_system_context_->path_manager()->CrackFileSystemPath(
- path, NULL, NULL, NULL)) {
+ if (!file_system_context()->path_manager()->CrackFileSystemPath(
+ path, origin_url, type, virtual_path)) {
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return false;
}
@@ -432,32 +554,35 @@ bool FileSystemOperation::VerifyFileSystemPathForRead(
}
bool FileSystemOperation::VerifyFileSystemPathForWrite(
- const FilePath& path, bool create) {
- GURL origin_url;
- FilePath virtual_path;
-
- // If we have no context, we just allow any operations.
- if (!file_system_context_.get())
+ const FilePath& path, bool create, GURL* origin_url, FileSystemType* type,
+ FilePath* virtual_path) {
+
+ // If we have no context, we just allow any operations, for testing.
+ // TODO(ericu): Revisit this hack for security.
+ if (!file_system_context()) {
+ *virtual_path = path;
+ *type = file_system_operation_context_.dest_type();
return true;
+ }
- if (!file_system_context_->path_manager()->CrackFileSystemPath(
- path, &origin_url, NULL, &virtual_path)) {
+ if (!file_system_context()->path_manager()->CrackFileSystemPath(
+ path, origin_url, type, virtual_path)) {
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return false;
}
// Any write access is disallowed on the root path.
- if (virtual_path.value().length() == 0 ||
- virtual_path.DirName().value() == virtual_path.value()) {
+ if (virtual_path->value().length() == 0 ||
+ virtual_path->DirName().value() == virtual_path->value()) {
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return false;
}
- if (create && FileSystemPathManager::IsRestrictedFileName(
- path.BaseName())) {
+ if (create && file_system_context()->path_manager()->IsRestrictedFileName(
+ *type, virtual_path->BaseName())) {
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return false;
}
// TODO(kinuko): the check must be moved to QuotaFileSystemFileUtil.
- if (!file_system_context_->IsStorageUnlimited(origin_url)) {
+ if (!file_system_context()->IsStorageUnlimited(*origin_url)) {
dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE);
return false;
}
diff --git a/webkit/fileapi/file_system_operation.h b/webkit/fileapi/file_system_operation.h
index a7ee52b..ae2b619 100644
--- a/webkit/fileapi/file_system_operation.h
+++ b/webkit/fileapi/file_system_operation.h
@@ -9,6 +9,7 @@
#include "base/file_path.h"
#include "base/file_util_proxy.h"
+#include "base/gtest_prod_util.h"
#include "base/message_loop_proxy.h"
#include "base/platform_file.h"
#include "base/ref_counted.h"
@@ -34,6 +35,7 @@ namespace fileapi {
class FileSystemCallbackDispatcher;
class FileSystemContext;
class FileWriterDelegate;
+class FileSystemOperationTest;
// This class is designed to serve one-time file system operation per instance.
// Only one method(CreateFile, CreateDirectory, Copy, Move, DirectoryExists,
@@ -44,9 +46,12 @@ class FileWriterDelegate;
class FileSystemOperation {
public:
// |dispatcher| will be owned by this class.
+ // |file_system_file_util| is optional; if supplied, it will not be deleted by
+ // the class. It's expecting a pointer to a singleton.
FileSystemOperation(FileSystemCallbackDispatcher* dispatcher,
scoped_refptr<base::MessageLoopProxy> proxy,
- FileSystemContext* file_system_context);
+ FileSystemContext* file_system_context,
+ FileSystemFileUtil* file_system_file_util);
virtual ~FileSystemOperation();
void OpenFileSystem(const GURL& origin_url,
@@ -81,6 +86,15 @@ class FileSystemOperation {
void Cancel(FileSystemOperation* cancel_operation);
private:
+ FileSystemContext* file_system_context() const {
+ return file_system_operation_context_.file_system_context();
+ }
+
+ FileSystemOperationContext* file_system_operation_context() {
+ return &file_system_operation_context_;
+ }
+ friend class FileSystemOperationTest;
+
// A callback used for OpenFileSystem.
void DidGetRootPath(bool success,
const FilePath& path,
@@ -118,15 +132,20 @@ class FileSystemOperation {
base::PassPlatformFile file,
bool created);
- // Checks the validity of a given |path| for reading.
+ // Checks the validity of a given |path| for reading, and cracks the path into
+ // root URL and virtual path components.
// Returns true if the given |path| is a valid FileSystem path.
// Otherwise it calls dispatcher's DidFail method with
// PLATFORM_FILE_ERROR_SECURITY and returns false.
// (Note: this doesn't delete this when it calls DidFail and returns false;
// it's the caller's responsibility.)
- bool VerifyFileSystemPathForRead(const FilePath& path);
+ bool VerifyFileSystemPathForRead(const FilePath& path,
+ GURL* root_url,
+ FileSystemType* type,
+ FilePath* virtual_path);
- // Checks the validity of a given |path| for writing.
+ // Checks the validity of a given |path| for writing, and cracks the path into
+ // root URL and virtual path components.
// Returns true if the given |path| is a valid FileSystem path, and
// its origin embedded in the path has the right to write.
// Otherwise it fires dispatcher's DidFail method with
@@ -140,7 +159,10 @@ class FileSystemOperation {
// (Note: this doesn't delete this when it calls DidFail and returns false;
// it's the caller's responsibility.)
bool VerifyFileSystemPathForWrite(const FilePath& path,
- bool create);
+ bool create,
+ GURL* root_url,
+ FileSystemType* type,
+ FilePath* virtual_path);
#ifndef NDEBUG
enum OperationType {
@@ -170,7 +192,6 @@ class FileSystemOperation {
scoped_ptr<FileSystemCallbackDispatcher> dispatcher_;
- scoped_refptr<FileSystemContext> file_system_context_;
FileSystemOperationContext file_system_operation_context_;
base::ScopedCallbackFactory<FileSystemOperation> callback_factory_;
diff --git a/webkit/fileapi/file_system_operation_context.cc b/webkit/fileapi/file_system_operation_context.cc
new file mode 100644
index 0000000..1a57137
--- /dev/null
+++ b/webkit/fileapi/file_system_operation_context.cc
@@ -0,0 +1,21 @@
+// 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/fileapi/file_system_operation_context.h"
+
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+FileSystemOperationContext::FileSystemOperationContext(
+ FileSystemContext* context,
+ FileSystemFileUtil* file_system_file_util)
+ : file_system_context_(context),
+ file_system_file_util_(file_system_file_util),
+ src_type_(kFileSystemTypeUnknown),
+ dest_type_(kFileSystemTypeUnknown) {
+}
+
+} // namespace fileapi
diff --git a/webkit/fileapi/file_system_operation_context.h b/webkit/fileapi/file_system_operation_context.h
index 68f5e47..d4c7f2f 100644
--- a/webkit/fileapi/file_system_operation_context.h
+++ b/webkit/fileapi/file_system_operation_context.h
@@ -5,24 +5,71 @@
#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_CONTEXT_H_
#define WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_CONTEXT_H_
+#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_file_util.h"
+#include "webkit/fileapi/file_system_types.h"
namespace fileapi {
+class FileSystemContext;
+
class FileSystemOperationContext {
public:
- FileSystemOperationContext(FileSystemFileUtil* file_system_file_util)
- : file_system_file_util_(file_system_file_util) {
+ FileSystemOperationContext(
+ FileSystemContext* context,
+ FileSystemFileUtil* file_system_file_util);
+
+ FileSystemContext* file_system_context() const {
+ return file_system_context_.get();
}
FileSystemFileUtil* file_system_file_util() const {
return file_system_file_util_;
}
+ void set_src_origin_url(const GURL& url) {
+ src_origin_url_ = url;
+ }
+
+ const GURL& src_origin_url() const {
+ return src_origin_url_;
+ }
+
+ void set_dest_origin_url(const GURL& url) {
+ dest_origin_url_ = url;
+ }
+
+ const GURL& dest_origin_url() const {
+ return dest_origin_url_;
+ }
+
+ FileSystemType src_type() const {
+ return src_type_;
+ }
+
+ void set_src_type(FileSystemType src_type) {
+ src_type_ = src_type;
+ }
+
+ FileSystemType dest_type() const {
+ return dest_type_;
+ }
+
+ void set_dest_type(FileSystemType dest_type) {
+ dest_type_ = dest_type;
+ }
+
private:
// This file_system_file_util_ is not "owned" by FileSystemOperationContext.
// It is supposed to be a pointer to a singleton.
+ scoped_refptr<FileSystemContext> file_system_context_;
FileSystemFileUtil* file_system_file_util_;
+
+ GURL src_origin_url_; // Also used for any single-path operation.
+ GURL dest_origin_url_;
+ FileSystemType src_type_; // Also used for any single-path operation.
+ FileSystemType dest_type_;
};
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_operation_unittest.cc b/webkit/fileapi/file_system_operation_unittest.cc
index 7e3a177..fe2b85d 100644
--- a/webkit/fileapi/file_system_operation_unittest.cc
+++ b/webkit/fileapi/file_system_operation_unittest.cc
@@ -10,6 +10,7 @@
#include "base/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
+#include "webkit/fileapi/file_system_file_util.h"
#include "webkit/fileapi/file_system_operation.h"
namespace fileapi {
@@ -97,10 +98,16 @@ class MockDispatcher : public FileSystemCallbackDispatcher {
};
FileSystemOperation* FileSystemOperationTest::operation() {
- return new FileSystemOperation(
+ FileSystemOperation* operation = new FileSystemOperation(
new MockDispatcher(this),
base::MessageLoopProxy::CreateForCurrentThread(),
- NULL);
+ NULL,
+ FileSystemFileUtil::GetInstance());
+ operation->file_system_operation_context()->set_src_type(
+ kFileSystemTypeTemporary);
+ operation->file_system_operation_context()->set_dest_type(
+ kFileSystemTypeTemporary);
+ return operation;
}
TEST_F(FileSystemOperationTest, TestMoveFailureSrcDoesntExist) {
diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc
index 61aa49e..64f3274 100644
--- a/webkit/fileapi/file_system_path_manager.cc
+++ b/webkit/fileapi/file_system_path_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -14,171 +14,33 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
#include "webkit/glue/webkit_glue.h"
// We use some of WebKit types for conversions between origin identifiers
// and origin URLs.
using WebKit::WebFileSystem;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebString;
using base::PlatformFileError;
-namespace fileapi {
-
-const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] =
- FILE_PATH_LITERAL("FileSystem");
-
-const char FileSystemPathManager::kPersistentName[] = "Persistent";
-const char FileSystemPathManager::kTemporaryName[] = "Temporary";
-
-static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
- FILE_PATH_LITERAL("chrome-");
-static const int kFileSystemUniqueLength = 16;
-static const unsigned kFileSystemUniqueDirectoryNameLength =
- kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;
-
-namespace {
-
-// Restricted names.
-// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
-static const char* const kRestrictedNames[] = {
- "con", "prn", "aux", "nul",
- "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
- "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
-};
-
-// Restricted chars.
-static const FilePath::CharType kRestrictedChars[] = {
- '/', '\\', '<', '>', ':', '?', '*', '"', '|',
-};
-
-inline std::string FilePathStringToASCII(
- const FilePath::StringType& path_string) {
-#if defined(OS_WIN)
- return WideToASCII(path_string);
-#elif defined(OS_POSIX)
- return path_string;
-#endif
-}
-
-FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
- // This can be anything but need to be unpredictable.
- static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
- FilePath::StringType unique(kFileSystemUniqueNamePrefix);
- for (int i = 0; i < kFileSystemUniqueLength; ++i)
- unique += letters[base::RandInt(0, arraysize(letters) - 2)];
- return unique;
-}
-
static const char kExtensionScheme[] = "chrome-extension";
-} // anonymous namespace
-
-class FileSystemPathManager::GetFileSystemRootPathTask
- : public base::RefCountedThreadSafe<
- FileSystemPathManager::GetFileSystemRootPathTask> {
- public:
- GetFileSystemRootPathTask(
- scoped_refptr<base::MessageLoopProxy> file_message_loop,
- const std::string& name,
- FileSystemPathManager::GetRootPathCallback* callback)
- : file_message_loop_(file_message_loop),
- origin_message_loop_proxy_(
- base::MessageLoopProxy::CreateForCurrentThread()),
- name_(name),
- callback_(callback) {
- }
-
- void Start(const GURL& origin_url,
- const FilePath& origin_base_path,
- bool create) {
- file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread,
- origin_url, origin_base_path, create));
- }
-
- private:
- void GetFileSystemRootPathOnFileThread(
- const GURL& origin_url,
- const FilePath& base_path,
- bool create) {
- FilePath root;
- if (ReadOriginDirectory(base_path, origin_url, &root)) {
- DispatchCallbackOnCallerThread(root);
- return;
- }
-
- if (!create) {
- DispatchCallbackOnCallerThread(FilePath());
- return;
- }
-
- // Creates the root directory.
- root = base_path.Append(CreateUniqueDirectoryName(origin_url));
- if (!file_util::CreateDirectory(root)) {
- DispatchCallbackOnCallerThread(FilePath());
- return;
- }
- DispatchCallbackOnCallerThread(root);
- }
-
- bool ReadOriginDirectory(const FilePath& base_path,
- const GURL& origin_url,
- FilePath* unique) {
- file_util::FileEnumerator file_enum(
- base_path, false /* recursive */,
- file_util::FileEnumerator::DIRECTORIES,
- FilePath::StringType(kFileSystemUniqueNamePrefix) +
- FILE_PATH_LITERAL("*"));
- FilePath current;
- bool found = false;
- while (!(current = file_enum.Next()).empty()) {
- if (current.BaseName().value().length() !=
- kFileSystemUniqueDirectoryNameLength)
- continue;
- if (found) {
- // TODO(kinuko): Should notify the user to ask for some action.
- LOG(WARNING) << "Unexpectedly found more than one FileSystem "
- << "directories for " << origin_url;
- return false;
- }
- found = true;
- *unique = current;
- }
- return !unique->empty();
- }
-
- void DispatchCallbackOnCallerThread(const FilePath& root_path) {
- origin_message_loop_proxy_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback,
- root_path));
- }
-
- void DispatchCallback(const FilePath& root_path) {
- callback_->Run(!root_path.empty(), root_path, name_);
- callback_.reset();
- }
-
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
- scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
- std::string name_;
- scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_;
-};
+namespace fileapi {
FileSystemPathManager::FileSystemPathManager(
scoped_refptr<base::MessageLoopProxy> file_message_loop,
const FilePath& profile_path,
bool is_incognito,
bool allow_file_access_from_files)
- : file_message_loop_(file_message_loop),
- base_path_(profile_path.Append(kFileSystemDirectory)),
- is_incognito_(is_incognito),
- allow_file_access_from_files_(allow_file_access_from_files) {
+ : is_incognito_(is_incognito),
+ allow_file_access_from_files_(allow_file_access_from_files),
+ sandbox_provider_(
+ new SandboxMountPointProvider(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this),
+ file_message_loop,
+ profile_path)) {
}
FileSystemPathManager::~FileSystemPathManager() {}
@@ -186,95 +48,88 @@ FileSystemPathManager::~FileSystemPathManager() {}
void FileSystemPathManager::GetFileSystemRootPath(
const GURL& origin_url, fileapi::FileSystemType type,
bool create, GetRootPathCallback* callback_ptr) {
- scoped_ptr<GetRootPathCallback> callback(callback_ptr);
- if (is_incognito_) {
- // TODO(kinuko): return an isolated temporary directory.
- callback->Run(false, FilePath(), std::string());
- return;
- }
- if (!IsAllowedScheme(origin_url)) {
- callback->Run(false, FilePath(), std::string());
- return;
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ sandbox_provider_->GetFileSystemRootPath(
+ origin_url, type, create, callback_ptr);
+ break;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ callback_ptr->Run(false, FilePath(), std::string());
}
+}
- std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
- FilePath origin_base_path = GetFileSystemBaseDirectoryForOriginAndType(
- base_path(), origin_identifier, type);
- if (origin_base_path.empty()) {
- callback->Run(false, FilePath(), std::string());
- return;
+FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url, FileSystemType type, bool create) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ return sandbox_provider_->GetFileSystemRootPathOnFileThread(
+ origin_url, type, create);
+ break;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ return FilePath();
}
-
- std::string type_string = GetFileSystemTypeString(type);
- DCHECK(!type_string.empty());
-
- scoped_refptr<GetFileSystemRootPathTask> task(
- new GetFileSystemRootPathTask(file_message_loop_,
- origin_identifier + ":" + type_string,
- callback.release()));
- task->Start(origin_url, origin_base_path, create);
}
bool FileSystemPathManager::CrackFileSystemPath(
const FilePath& path, GURL* origin_url, FileSystemType* type,
FilePath* virtual_path) const {
- // Any paths that includes parent references are considered invalid.
- if (path.ReferencesParent())
- return false;
-
- // The path should be a child of the profile FileSystem path.
- FilePath relative;
- if (!base_path_.AppendRelativePath(path, &relative))
- return false;
-
- // The relative path from the profile FileSystem path should contain
- // at least three components, one for storage identifier, one for type
- // and one for the 'unique' part.
- std::vector<FilePath::StringType> components;
- relative.GetComponents(&components);
- if (components.size() < 3)
- return false;
+ // TODO(ericu):
+ // Paths come in here [for now] as a URL, followed by a virtual path in
+ // platform format. For example, on Windows, this will look like
+ // filesystem:http://www.example.com/temporary/\path\to\file.txt.
+ // A potentially dangerous malicious path on Windows might look like:
+ // filesystem:http://www.example.com/temporary/foo/../../\path\to\file.txt.
+ // This code is ugly, but will get cleaned up as we fix the calling side.
+ // Eventually there won't be a distinction between a filesystem path and a
+ // filesystem URL--they'll all be URLs.
+ // We should be passing these to WebKit as string, not FilePath, for ease of
+ // manipulation, or possibly as GURL/KURL.
+
+ std::string path_as_string;
+#ifdef OS_WIN
+ path_as_string = WideToUTF8(path.value());
+#else
+ path_as_string = path.value();
+#endif
+ GURL path_as_url(path_as_string);
- // The second component of the relative path to the root directory
- // must be kPersistent or kTemporary.
- if (!IsStringASCII(components[1]))
+ FilePath local_path;
+ GURL local_url;
+ FileSystemType local_type;
+ if (!CrackFileSystemURL(path_as_url, &local_url, &local_type, &local_path))
return false;
- std::string ascii_type_component = FilePathStringToASCII(components[1]);
- FileSystemType cracked_type = kFileSystemTypeUnknown;
- if (ascii_type_component == kPersistentName)
- cracked_type = kFileSystemTypePersistent;
- else if (ascii_type_component == kTemporaryName)
- cracked_type = kFileSystemTypeTemporary;
- else
- return false;
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ // TODO(ericu): This puts the separators back to windows-standard; they come
+ // out of the above code as '/' no matter the platform. Long-term, we'll
+ // want to let the underlying FileSystemFileUtil implementation do this part,
+ // since they won't all need it.
+ local_path = local_path.NormalizeWindowsPathSeparators();
+#endif
- DCHECK(cracked_type != kFileSystemTypeUnknown);
+ // Any paths that include parent references are considered invalid.
+ // These should have been taken care of in CrackFileSystemURL.
+ DCHECK(!local_path.ReferencesParent());
- // The given |path| seems valid. Populates the |origin_url|, |type|
+ // The given |local_path| seems valid. Populates the |origin_url|, |type|
// and |virtual_path| if they are given.
if (origin_url) {
- WebSecurityOrigin web_security_origin =
- WebSecurityOrigin::createFromDatabaseIdentifier(
- webkit_glue::FilePathStringToWebString(components[0]));
- *origin_url = GURL(web_security_origin.toString());
-
- // We need this work-around for file:/// URIs as
- // createFromDatabaseIdentifier returns empty origin_url for them.
- if (allow_file_access_from_files_ && origin_url->spec().empty() &&
- components[0].find(FILE_PATH_LITERAL("file")) == 0)
- *origin_url = GURL("file:///");
+ *origin_url = local_url;
}
if (type)
- *type = cracked_type;
+ *type = local_type;
if (virtual_path) {
- virtual_path->clear();
- for (size_t i = 3; i < components.size(); ++i)
- *virtual_path = virtual_path->Append(components[i]);
+ *virtual_path = local_path;
}
return true;
@@ -289,87 +144,27 @@ bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const {
}
// static
-bool FileSystemPathManager::IsRestrictedFileName(const FilePath& filename) {
- if (filename.value().empty())
- return false;
-
- if (IsWhitespace(filename.value()[filename.value().size() - 1]) ||
- filename.value()[filename.value().size() - 1] == '.')
- return true;
-
- std::string filename_lower = StringToLowerASCII(
- FilePathStringToASCII(filename.value()));
-
- for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
- // Exact match.
- if (filename_lower == kRestrictedNames[i])
- return true;
- // Starts with "RESTRICTED_NAME.".
- if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0)
- return true;
- }
-
- for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
- if (filename.value().find(kRestrictedChars[i]) !=
- FilePath::StringType::npos)
- return true;
- }
-
- return false;
-}
-
-// static
std::string FileSystemPathManager::GetFileSystemTypeString(
fileapi::FileSystemType type) {
if (type == fileapi::kFileSystemTypeTemporary)
- return fileapi::FileSystemPathManager::kTemporaryName;
+ return fileapi::SandboxMountPointProvider::kTemporaryName;
else if (type == fileapi::kFileSystemTypePersistent)
- return fileapi::FileSystemPathManager::kPersistentName;
+ return fileapi::SandboxMountPointProvider::kPersistentName;
return std::string();
}
-// static
-std::string FileSystemPathManager::GetOriginIdentifierFromURL(
- const GURL& url) {
- WebKit::WebSecurityOrigin web_security_origin =
- WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
- return web_security_origin.databaseIdentifier().utf8();
-}
-
-// static
-FilePath FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType(
- const FilePath& base_path, const std::string& origin_identifier,
- fileapi::FileSystemType type) {
- if (origin_identifier.empty())
- return FilePath();
- std::string type_string = GetFileSystemTypeString(type);
- if (type_string.empty()) {
- LOG(WARNING) << "Unknown filesystem type is requested:" << type;
- return FilePath();
+// Checks if a given |name| contains any restricted names/chars in it.
+bool FileSystemPathManager::IsRestrictedFileName(
+ FileSystemType type, const FilePath& filename) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ return sandbox_provider_->IsRestrictedFileName(filename);
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ return true;
}
- return base_path.AppendASCII(origin_identifier)
- .AppendASCII(type_string);
-}
-
-FileSystemPathManager::OriginEnumerator::OriginEnumerator(
- const FilePath& base_path)
- : enumerator_(base_path, false /* recursive */,
- file_util::FileEnumerator::DIRECTORIES) {
-}
-
-std::string FileSystemPathManager::OriginEnumerator::Next() {
- current_ = enumerator_.Next();
- return FilePathStringToASCII(current_.BaseName().value());
-}
-
-bool FileSystemPathManager::OriginEnumerator::HasTemporary() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- FileSystemPathManager::kTemporaryName));
-}
-
-bool FileSystemPathManager::OriginEnumerator::HasPersistent() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- FileSystemPathManager::kPersistentName));
}
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h
index 28082aa..c1d2df9 100644
--- a/webkit/fileapi/file_system_path_manager.h
+++ b/webkit/fileapi/file_system_path_manager.h
@@ -19,6 +19,8 @@ class MessageLoopProxy;
namespace fileapi {
+class SandboxMountPointProvider;
+
// TODO(kinuko): Probably this module must be called FileSystemPathUtil
// or something similar.
@@ -49,11 +51,17 @@ class FileSystemPathManager {
// Retrieves the root path for the given |origin_url| and |type|, and
// calls the given |callback| with the root path and name.
// If |create| is true this also creates the directory if it doesn't exist.
- void GetFileSystemRootPath(const GURL& origin_url,
- fileapi::FileSystemType type,
+ virtual void GetFileSystemRootPath(const GURL& origin_url,
+ FileSystemType type,
bool create,
- GetRootPathCallback* callback);
-
+ FileSystemPathManager::GetRootPathCallback*
+ callback);
+
+ // Like GetFileSystemRootPath, but synchronous, and can be called only while
+ // running on the file thread.
+ virtual FilePath GetFileSystemRootPathOnFileThread(const GURL& origin_url,
+ FileSystemType type,
+ bool create);
// Cracks the given |path|, retrieves the information embedded in the path
// and populates |origin_url|, |type| and |virtual_path|. The |virtual_path|
// is a sandboxed path in the file system, i.e. the relative path to the
@@ -67,66 +75,26 @@ class FileSystemPathManager {
// filesystem.
bool IsAllowedScheme(const GURL& url) const;
- // The FileSystem directory name.
- static const FilePath::CharType kFileSystemDirectory[];
-
- static const char kPersistentName[];
- static const char kTemporaryName[];
-
- const FilePath& base_path() const {
- return base_path_;
- }
-
- // Checks if a given |name| contains any restricted names/chars in it.
- static bool IsRestrictedFileName(const FilePath& filename);
-
// Returns the string for the given |type|.
// Returns an empty string if the |type| is invalid.
static std::string GetFileSystemTypeString(fileapi::FileSystemType type);
- // Returns the origin identifier string, which is used as a part of the
- // sandboxed path component, for the given |url|.
- static std::string GetOriginIdentifierFromURL(const GURL& url);
-
- // Gets a base directory path of the sandboxed filesystem that is
- // specified by |origin_identifier| and |type|.
- // |base_path| must be pointing the FileSystem's data directory
- // under the profile directory, i.e. <profile_dir>/kFileSystemDirectory.
- // Returns an empty path if any of the given parameters are invalid.
- // Returned directory path does not contain 'unique' part, therefore
- // it is not an actural root path for the filesystem.
- static FilePath GetFileSystemBaseDirectoryForOriginAndType(
- const FilePath& base_path,
- const std::string& origin_identifier,
- fileapi::FileSystemType type);
-
- // Enumerates origins under the given |base_path|.
- // This must be used on the FILE thread.
- class OriginEnumerator {
- public:
- OriginEnumerator(const FilePath& base_path);
-
- // Returns the next origin identifier. Returns empty if there are no
- // more origins.
- std::string Next();
-
- bool HasTemporary();
- bool HasPersistent();
- const FilePath& path() { return current_; }
-
- private:
- file_util::FileEnumerator enumerator_;
- FilePath current_;
- };
+ // Checks if a given |name| contains any restricted names/chars in it.
+ bool IsRestrictedFileName(FileSystemType type,
+ const FilePath& filename);
- private:
- class GetFileSystemRootPathTask;
+ SandboxMountPointProvider* sandbox_provider() const {
+ return sandbox_provider_.get();
+ }
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+ bool is_incognito() const {
+ return is_incognito_;
+ }
- const FilePath base_path_;
+ private:
const bool is_incognito_;
const bool allow_file_access_from_files_;
+ scoped_ptr<SandboxMountPointProvider> sandbox_provider_;
DISALLOW_COPY_AND_ASSIGN(FileSystemPathManager);
};
diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc
index 3d6c831..8f004c2 100644
--- a/webkit/fileapi/file_system_path_manager_unittest.cc
+++ b/webkit/fileapi/file_system_path_manager_unittest.cc
@@ -17,6 +17,8 @@
#include "base/scoped_temp_dir.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
using namespace fileapi;
@@ -212,7 +214,7 @@ class FileSystemPathManagerTest : public testing::Test {
FilePath data_path() { return data_dir_.path(); }
FilePath file_system_path() {
return data_dir_.path().Append(
- FileSystemPathManager::kFileSystemDirectory);
+ SandboxMountPointProvider::kFileSystemDirectory);
}
private:
@@ -345,16 +347,24 @@ TEST_F(FileSystemPathManagerTest, GetRootPathFileURIWithAllowFlag) {
TEST_F(FileSystemPathManagerTest, VirtualPathFromFileSystemPathTest) {
scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false));
- FilePath root_path;
- EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"),
- fileapi::kFileSystemTypeTemporary,
- true /* create */, &root_path));
+ GURL root_url = GetFileSystemRootURI(
+ GURL("http://foo.com/"), fileapi::kFileSystemTypeTemporary);
+ FilePath root_path = FilePath().AppendASCII(root_url.spec());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPathToVirtualPathTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "PathToVirtualPath #"
<< i << " " << kPathToVirtualPathTestCases[i]);
- FilePath absolute_path = root_path.AppendASCII(
- kPathToVirtualPathTestCases[i]);
+ FilePath absolute_path;
+ // TODO(ericu): Clean this up when we've got more sane path-handling.
+ // This hack is necessary because root_path is actually a URL [ending with a
+ // forward slash], and AppendASCII("") on Windows will delete the trailing
+ // slash, making the path invalid as far as CrackFileSystemPath is
+ // concerned.
+ if (strlen(kPathToVirtualPathTestCases[i]))
+ absolute_path = root_path.AppendASCII(
+ kPathToVirtualPathTestCases[i]);
+ else
+ absolute_path = root_path;
FilePath virtual_path;
EXPECT_TRUE(manager->CrackFileSystemPath(absolute_path, NULL, NULL,
&virtual_path));
@@ -369,19 +379,18 @@ TEST_F(FileSystemPathManagerTest, VirtualPathFromFileSystemPathTest) {
TEST_F(FileSystemPathManagerTest, TypeFromFileSystemPathTest) {
scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false));
- FilePath root_path;
fileapi::FileSystemType type;
- EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"),
- fileapi::kFileSystemTypeTemporary,
- true /* create */, &root_path));
+ GURL root_url = GetFileSystemRootURI(
+ GURL("http://foo.com/"), fileapi::kFileSystemTypeTemporary);
+ FilePath root_path = FilePath().AppendASCII(root_url.spec());
FilePath path = root_path.AppendASCII("test");
EXPECT_TRUE(manager->CrackFileSystemPath(path, NULL, &type, NULL));
EXPECT_EQ(fileapi::kFileSystemTypeTemporary, type);
- EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"),
- fileapi::kFileSystemTypePersistent,
- true /* create */, &root_path));
+ root_url = GetFileSystemRootURI(
+ GURL("http://foo.com/"), fileapi::kFileSystemTypePersistent);
+ root_path = FilePath().AppendASCII(root_url.spec());
path = root_path.AppendASCII("test");
EXPECT_TRUE(manager->CrackFileSystemPath(path, NULL, &type, NULL));
EXPECT_EQ(fileapi::kFileSystemTypePersistent, type);
@@ -389,9 +398,9 @@ TEST_F(FileSystemPathManagerTest, TypeFromFileSystemPathTest) {
TEST_F(FileSystemPathManagerTest, CheckValidPath) {
scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false));
- FilePath root_path;
- EXPECT_TRUE(GetRootPath(manager.get(), GURL("http://foo.com/"),
- kFileSystemTypePersistent, true, &root_path));
+ GURL root_url = GetFileSystemRootURI(
+ GURL("http://foo.com/"), fileapi::kFileSystemTypePersistent);
+ FilePath root_path = FilePath().AppendASCII(root_url.spec());
// The root path must be valid, but upper directories or directories
// that are not in our temporary or persistent directory must be
@@ -409,6 +418,9 @@ TEST_F(FileSystemPathManagerTest, CheckValidPath) {
SCOPED_TRACE(testing::Message() << "CheckValidPath #" << i << " "
<< kCheckValidPathTestCases[i].path);
FilePath path(kCheckValidPathTestCases[i].path);
+#ifdef FILE_PATH_USES_WIN_SEPARATORS
+ path = path.NormalizeWindowsPathSeparators();
+#endif
if (!path.IsAbsolute())
path = root_path.Append(path);
EXPECT_EQ(kCheckValidPathTestCases[i].expected_valid,
@@ -417,88 +429,12 @@ TEST_F(FileSystemPathManagerTest, CheckValidPath) {
}
TEST_F(FileSystemPathManagerTest, IsRestrictedName) {
+ scoped_ptr<FileSystemPathManager> manager(NewPathManager(false, false));
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kIsRestrictedNameTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "IsRestrictedName #" << i << " "
<< kIsRestrictedNameTestCases[i].name);
FilePath name(kIsRestrictedNameTestCases[i].name);
EXPECT_EQ(kIsRestrictedNameTestCases[i].expected_dangerous,
- FileSystemPathManager::IsRestrictedFileName(name));
+ manager->IsRestrictedFileName(kFileSystemTypeTemporary, name));
}
}
-
-class FileSystemPathManagerOriginEnumeratorTest : public testing::Test {
- public:
- void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- enumerator_.reset(new FileSystemPathManager::OriginEnumerator(
- data_dir_.path()));
- }
-
- FileSystemPathManager::OriginEnumerator* enumerator() const {
- return enumerator_.get();
- }
-
- protected:
- void CreateOriginTypeDirectory(const std::string& origin_identifier,
- fileapi::FileSystemType type) {
- std::string type_string =
- FileSystemPathManager::GetFileSystemTypeString(type);
- ASSERT_TRUE(!type_string.empty());
- FilePath target = data_dir_.path().AppendASCII(origin_identifier)
- .AppendASCII(type_string);
- file_util::CreateDirectory(target);
- ASSERT_TRUE(file_util::DirectoryExists(target));
- }
-
- ScopedTempDir data_dir_;
- scoped_ptr<FileSystemPathManager::OriginEnumerator> enumerator_;
-};
-
-TEST_F(FileSystemPathManagerOriginEnumeratorTest, Empty) {
- ASSERT_TRUE(enumerator()->Next().empty());
-}
-
-TEST_F(FileSystemPathManagerOriginEnumeratorTest, EnumerateOrigins) {
- const char* temporary_origins[] = {
- "http_www.bar.com_0",
- "http_www.foo.com_0",
- "http_www.foo.com_80",
- "http_www.example.com_8080",
- "http_www.google.com_80",
- };
- const char* persistent_origins[] = {
- "http_www.bar.com_0",
- "http_www.foo.com_8080",
- "http_www.foo.com_80",
- };
- size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
- size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
- std::set<std::string> temporary_set, persistent_set;
- for (size_t i = 0; i < temporary_size; ++i) {
- CreateOriginTypeDirectory(temporary_origins[i],
- fileapi::kFileSystemTypeTemporary);
- temporary_set.insert(temporary_origins[i]);
- }
- for (size_t i = 0; i < persistent_size; ++i) {
- CreateOriginTypeDirectory(persistent_origins[i], kFileSystemTypePersistent);
- persistent_set.insert(persistent_origins[i]);
- }
-
- size_t temporary_actual_size = 0;
- size_t persistent_actual_size = 0;
- std::string current;
- while (!(current = enumerator()->Next()).empty()) {
- SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current);
- if (enumerator()->HasTemporary()) {
- ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
- ++temporary_actual_size;
- }
- if (enumerator()->HasPersistent()) {
- ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
- ++persistent_actual_size;
- }
- }
-
- ASSERT_EQ(temporary_size, temporary_actual_size);
- ASSERT_EQ(persistent_size, persistent_actual_size);
-}
diff --git a/webkit/fileapi/file_system_usage_tracker.cc b/webkit/fileapi/file_system_usage_tracker.cc
index 9456f2a..85498d3 100644
--- a/webkit/fileapi/file_system_usage_tracker.cc
+++ b/webkit/fileapi/file_system_usage_tracker.cc
@@ -15,6 +15,7 @@
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_path_manager.h"
#include "webkit/fileapi/file_system_usage_cache.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
namespace fileapi {
@@ -98,7 +99,7 @@ FileSystemUsageTracker::FileSystemUsageTracker(
bool is_incognito)
: file_message_loop_(file_message_loop),
base_path_(profile_path.Append(
- FileSystemPathManager::kFileSystemDirectory)),
+ SandboxMountPointProvider::kFileSystemDirectory)),
is_incognito_(is_incognito) {
DCHECK(file_message_loop);
}
@@ -123,7 +124,7 @@ void FileSystemUsageTracker::GetOriginUsage(
}
std::string origin_identifier =
- FileSystemPathManager::GetOriginIdentifierFromURL(origin_url);
+ SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url);
std::string type_string =
FileSystemPathManager::GetFileSystemTypeString(type);
std::string fs_identifier = origin_identifier + ":" + type_string;
@@ -139,7 +140,7 @@ void FileSystemUsageTracker::GetOriginUsage(
// Get the filesystem base path (i.e. "FileSystem/<origin>/<type>",
// without unique part).
FilePath origin_base_path =
- FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType(
+ SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
base_path_, origin_identifier, type);
if (origin_base_path.empty()) {
// The directory does not exist.
diff --git a/webkit/fileapi/file_system_usage_tracker.h b/webkit/fileapi/file_system_usage_tracker.h
index 10a5177..af292a1 100644
--- a/webkit/fileapi/file_system_usage_tracker.h
+++ b/webkit/fileapi/file_system_usage_tracker.h
@@ -24,11 +24,10 @@ class MessageLoopProxy;
namespace fileapi {
-// Owned by the SandboxedFileSystemContext, which is a per-profile
-// instance, and has the same lifetime as the SandboxedFileSystemContext.
-// It's going to be created and destroyed on the IO thread in chrome.
-// (The destruction on the same thread where it is created was guaranteed
-// by its owner, SandboxedFileSystemContext.)
+// Owned by the FileSystemContext, which is a per-profile instance, and has the
+// same lifetime as the FileSystemContext. It's going to be created and
+// destroyed on the IO thread in chrome. (The destruction on the same thread
+// where it is created was guaranteed by its owner, FileSystemContext.)
class FileSystemUsageTracker {
public:
FileSystemUsageTracker(
diff --git a/webkit/fileapi/file_system_usage_tracker_unittest.cc b/webkit/fileapi/file_system_usage_tracker_unittest.cc
index 8d0c2c0..a78aba3 100644
--- a/webkit/fileapi/file_system_usage_tracker_unittest.cc
+++ b/webkit/fileapi/file_system_usage_tracker_unittest.cc
@@ -13,9 +13,9 @@
#include "googleurl/src/gurl.h"
#include "base/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/fileapi/file_system_path_manager.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_usage_cache.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
using namespace fileapi;
@@ -71,10 +71,10 @@ class FileSystemUsageTrackerTest : public testing::Test {
FilePath GetOriginBasePath(const GURL& origin_url,
fileapi::FileSystemType type) {
return
- FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType(
+ SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
data_dir_.path().Append(
- FileSystemPathManager::kFileSystemDirectory),
- FileSystemPathManager::GetOriginIdentifierFromURL(origin_url),
+ SandboxMountPointProvider::kFileSystemDirectory),
+ SandboxMountPointProvider::GetOriginIdentifierFromURL(origin_url),
type);
}
diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc
index 07aa5a6..ae36fa850 100644
--- a/webkit/fileapi/file_system_util.cc
+++ b/webkit/fileapi/file_system_util.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "base/file_path.h"
+#include "base/logging.h"
#include "base/sys_string_conversions.h"
#include "googleurl/src/gurl.h"
#include "net/base/escape.h"
@@ -19,27 +20,61 @@ static const char kTemporaryDir[] = "/temporary/";
bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
FilePath* file_path) {
- *origin_url = GURL();
- *type = kFileSystemTypeUnknown;
- *file_path = FilePath();
+ GURL origin;
+ FileSystemType file_system_type;
if (url.scheme() != "filesystem")
return false;
- GURL bare_url(url.path());
- *origin_url = bare_url.GetOrigin();
+ std::string temp = url.path();
+ // TODO(ericu) remove this code when that ceases to be true, which should be
+ // soon.
+ // On Windows, this will have backslashes for now.
+ // url will look something like:
+ // filesystem:http://example.com/temporary/\dir\file.txt
+ // temp will look something like:
+ // http://example.com/temporary/\dir\file.txt
+ // On posix, url will look something like:
+ // filesystem:http://example.com/temporary/dir/file.txt
+ // temp will look something like:
+ // http://example.com/temporary/dir/file.txt
+ size_t pos = temp.find('\\');
+ for (; pos != std::string::npos; pos = temp.find('\\', pos + 1)) {
+ temp[pos] = '/';
+ }
+ // TODO(ericu): This should probably be done elsewhere after the stackable
+ // layers are properly in. We're supposed to reject any paths that contain
+ // '..' segments, but the GURL constructor is helpfully resolving them for us.
+ // Make sure there aren't any before we call it.
+ pos = temp.find("..");
+ for (; pos != std::string::npos; pos = temp.find("..", pos + 1)) {
+ if ((pos == 0 || temp[pos - 1] == '/') &&
+ (pos == temp.length() - 2 || temp[pos + 2] == '/'))
+ return false;
+ }
+
+ // bare_url will look something like:
+ // http://example.com/temporary//dir/file.txt [on Windows; the double slash
+ // before dir will be single on posix].
+ GURL bare_url(temp);
+
+ // The input URL was malformed, bail out early.
+ if (bare_url.path().empty())
+ return false;
+
+ origin = bare_url.GetOrigin();
// The input URL was malformed, bail out early.
- if (origin_url->is_empty() || bare_url.path().empty())
+ if (origin.is_empty())
return false;
std::string path = UnescapeURLComponent(bare_url.path(),
UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
if (path.compare(0, strlen(kPersistentDir), kPersistentDir) == 0) {
- *type = kFileSystemTypePersistent;
+ file_system_type = kFileSystemTypePersistent;
path = path.substr(strlen(kPersistentDir));
} else if (path.compare(0, strlen(kTemporaryDir), kTemporaryDir) == 0) {
- *type = kFileSystemTypeTemporary;
+ file_system_type = kFileSystemTypeTemporary;
path = path.substr(strlen(kTemporaryDir));
} else {
return false;
@@ -50,13 +85,36 @@ bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
path.erase(0, 1);
#if defined(OS_WIN)
- const FilePath::StringType& sys_path = base::SysUTF8ToWide(path);
+ const FilePath::StringType sys_path = base::SysUTF8ToWide(path);
#elif defined(OS_POSIX)
- const FilePath::StringType& sys_path = path;
+ const FilePath::StringType sys_path = path;
#endif
+ if (origin_url)
+ *origin_url = origin;
+ if (type)
+ *type = file_system_type;
+ if (file_path)
+ *file_path = FilePath(sys_path);
- *file_path = FilePath(sys_path);
return true;
}
+GURL GetFileSystemRootURI(
+ const GURL& origin_url, fileapi::FileSystemType type) {
+ std::string path("filesystem:");
+ path += origin_url.spec();
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ path += (kTemporaryDir + 1); // We don't want the leading slash.
+ break;
+ case kFileSystemTypePersistent:
+ path += (kPersistentDir + 1); // We don't want the leading slash.
+ break;
+ default:
+ NOTREACHED();
+ return GURL();
+ }
+ return GURL(path);
+}
+
} // namespace fileapi
diff --git a/webkit/fileapi/file_system_util.h b/webkit/fileapi/file_system_util.h
index 4331b1a..b858c1b 100644
--- a/webkit/fileapi/file_system_util.h
+++ b/webkit/fileapi/file_system_util.h
@@ -13,9 +13,13 @@ class GURL;
namespace fileapi {
+// The file_path this returns will be using '/' as a path separator, no matter
+// what platform you're on.
bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type,
FilePath* file_path);
+GURL GetFileSystemRootURI(const GURL& origin_url, fileapi::FileSystemType type);
+
} // namespace fileapi
#endif // WEBKIT_FILEAPI_FILE_SYSTEM_UTIL_H_
diff --git a/webkit/fileapi/file_system_util_unittest.cc b/webkit/fileapi/file_system_util_unittest.cc
index 7cb4c59..e08fec7 100644
--- a/webkit/fileapi/file_system_util_unittest.cc
+++ b/webkit/fileapi/file_system_util_unittest.cc
@@ -71,5 +71,19 @@ TEST_F(FileSystemUtilTest, RejectMalformedURL) {
EXPECT_FALSE(CrackFileSystemURL("filesystem:foobar/file"));
}
+TEST_F(FileSystemUtilTest, GetTempFileSystemRootURI) {
+ GURL origin_url("http://chromium.org");
+ fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ GURL uri = GURL("filesystem:http://chromium.org/temporary/");
+ EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
+}
+
+TEST_F(FileSystemUtilTest, GetPersistentFileSystemRootURI) {
+ GURL origin_url("http://chromium.org");
+ fileapi::FileSystemType type = fileapi::kFileSystemTypePersistent;
+ GURL uri = GURL("filesystem:http://chromium.org/persistent/");
+ EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
+}
+
} // namespace (anonymous)
} // namespace fileapi
diff --git a/webkit/fileapi/local_file_system_file_util.cc b/webkit/fileapi/local_file_system_file_util.cc
new file mode 100644
index 0000000..a017d57
--- /dev/null
+++ b/webkit/fileapi/local_file_system_file_util.cc
@@ -0,0 +1,178 @@
+// 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/fileapi/local_file_system_file_util.h"
+
+#include "base/file_util_proxy.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/fileapi/file_system_context.h"
+#include "webkit/fileapi/file_system_operation_context.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+LocalFileSystemFileUtil* LocalFileSystemFileUtil::GetInstance() {
+ return Singleton<LocalFileSystemFileUtil>::get();
+}
+
+PlatformFileError LocalFileSystemFileUtil::CreateOrOpen(
+ FileSystemOperationContext* context,
+ const FilePath& file_path, int file_flags,
+ PlatformFile* file_handle, bool* created) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->CreateOrOpen(
+ context, local_path, file_flags, file_handle, created);
+}
+
+PlatformFileError LocalFileSystemFileUtil::EnsureFileExists(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool* created) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->EnsureFileExists(
+ context, local_path, created);
+}
+
+PlatformFileError LocalFileSystemFileUtil::GetFileInfo(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ base::PlatformFileInfo* file_info) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->GetFileInfo(
+ context, local_path, file_info);
+}
+
+PlatformFileError LocalFileSystemFileUtil::ReadDirectory(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ std::vector<base::FileUtilProxy::Entry>* entries) {
+ // TODO(kkanetkar): Implement directory read in multiple chunks.
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->ReadDirectory(
+ context, local_path, entries);
+}
+
+PlatformFileError LocalFileSystemFileUtil::CreateDirectory(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool exclusive,
+ bool recursive) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->CreateDirectory(
+ context, local_path, exclusive, recursive);
+}
+
+PlatformFileError LocalFileSystemFileUtil::Copy(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path) {
+ // TODO(ericu): If they share a root URL, this could be optimized.
+ FilePath local_src_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ src_file_path);
+ if (local_src_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ FilePath local_dest_path =
+ GetLocalPath(context, context->dest_origin_url(), context->dest_type(),
+ dest_file_path);
+ if (local_dest_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->Copy(
+ context, local_src_path, local_dest_path);
+}
+
+PlatformFileError LocalFileSystemFileUtil::Move(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path) {
+ // TODO(ericu): If they share a root URL, this could be optimized.
+ FilePath local_src_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ src_file_path);
+ if (local_src_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ FilePath local_dest_path =
+ GetLocalPath(context, context->dest_origin_url(), context->dest_type(),
+ dest_file_path);
+ if (local_dest_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->Move(
+ context, local_src_path, local_dest_path);
+}
+
+PlatformFileError LocalFileSystemFileUtil::Delete(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool recursive) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->Delete(
+ context, local_path, recursive);
+}
+
+PlatformFileError LocalFileSystemFileUtil::Touch(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->Touch(
+ context, local_path, last_access_time, last_modified_time);
+}
+
+PlatformFileError LocalFileSystemFileUtil::Truncate(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ int64 length) {
+ FilePath local_path =
+ GetLocalPath(context, context->src_origin_url(), context->src_type(),
+ file_path);
+ if (local_path.empty())
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return FileSystemFileUtil::GetInstance()->Truncate(
+ context, local_path, length);
+}
+
+FilePath LocalFileSystemFileUtil::GetLocalPath(
+ FileSystemOperationContext* context,
+ const GURL& origin_url,
+ FileSystemType type,
+ const FilePath& virtual_path) {
+ FilePath root = context->file_system_context()->path_manager()->
+ GetFileSystemRootPathOnFileThread(origin_url, type, false);
+ if (root.empty())
+ return FilePath();
+ return root.Append(virtual_path);
+}
+
+} // namespace fileapi
diff --git a/webkit/fileapi/local_file_system_file_util.h b/webkit/fileapi/local_file_system_file_util.h
new file mode 100644
index 0000000..6fc2e11
--- /dev/null
+++ b/webkit/fileapi/local_file_system_file_util.h
@@ -0,0 +1,112 @@
+// 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_FILEAPI_LOCAL_FILE_SYSTEM_FILE_UTIL_H_
+#define WEBKIT_FILEAPI_LOCAL_FILE_SYSTEM_FILE_UTIL_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/file_util_proxy.h"
+#include "base/logging.h"
+#include "base/platform_file.h"
+#include "base/ref_counted.h"
+#include "base/singleton.h"
+#include "base/tracked_objects.h"
+#include "webkit/fileapi/file_system_file_util.h"
+#include "webkit/fileapi/file_system_types.h"
+
+namespace base {
+struct PlatformFileInfo;
+class MessageLoopProxy;
+class Time;
+}
+
+class GURL;
+
+namespace fileapi {
+
+using base::PlatformFile;
+using base::PlatformFileError;
+
+class FileSystemOperationContext;
+
+class LocalFileSystemFileUtil : public FileSystemFileUtil {
+ public:
+ static LocalFileSystemFileUtil* GetInstance();
+
+ virtual PlatformFileError CreateOrOpen(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ int file_flags,
+ PlatformFile* file_handle,
+ bool* created);
+
+ virtual PlatformFileError EnsureFileExists(
+ FileSystemOperationContext* context,
+ const FilePath& file_path, bool* created);
+
+ virtual PlatformFileError GetFileInfo(
+ FileSystemOperationContext* context,
+ const FilePath& file_, base::PlatformFileInfo* file_info);
+
+ virtual PlatformFileError ReadDirectory(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ std::vector<base::FileUtilProxy::Entry>* entries);
+
+ virtual PlatformFileError CreateDirectory(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool exclusive,
+ bool recursive);
+
+ virtual PlatformFileError Copy(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path);
+
+ virtual PlatformFileError Move(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path);
+
+ virtual PlatformFileError Delete(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool recursive);
+
+ virtual PlatformFileError Touch(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time);
+
+ virtual PlatformFileError Truncate(
+ FileSystemOperationContext* context,
+ const FilePath& path,
+ int64 length);
+
+ protected:
+ LocalFileSystemFileUtil() { }
+
+ friend struct DefaultSingletonTraits<LocalFileSystemFileUtil>;
+ DISALLOW_COPY_AND_ASSIGN(LocalFileSystemFileUtil);
+
+ private:
+ // Given the filesystem's root URL and a virtual path, produces a real, full
+ // local path.
+ FilePath GetLocalPath(
+ FileSystemOperationContext* context,
+ const GURL& origin_url,
+ FileSystemType type,
+ const FilePath& virtual_path);
+
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_LOCAL_FILE_SYSTEM_FILE_UTIL_H_
diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc
new file mode 100644
index 0000000..ac82cc8
--- /dev/null
+++ b/webkit/fileapi/sandbox_mount_point_provider.cc
@@ -0,0 +1,312 @@
+// 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/fileapi/sandbox_mount_point_provider.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/rand_util.h"
+#include "base/scoped_callback_factory.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace {
+
+static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
+ FILE_PATH_LITERAL("chrome-");
+static const int kFileSystemUniqueLength = 16;
+static const unsigned kFileSystemUniqueDirectoryNameLength =
+ kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;
+
+// Restricted names.
+// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
+static const char* const kRestrictedNames[] = {
+ "con", "prn", "aux", "nul",
+ "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
+ "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
+};
+
+// Restricted chars.
+static const FilePath::CharType kRestrictedChars[] = {
+ '/', '\\', '<', '>', ':', '?', '*', '"', '|',
+};
+
+inline std::string FilePathStringToASCII(
+ const FilePath::StringType& path_string) {
+#if defined(OS_WIN)
+ return WideToASCII(path_string);
+#elif defined(OS_POSIX)
+ return path_string;
+#endif
+}
+
+FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
+ // This can be anything but need to be unpredictable.
+ static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+ FilePath::StringType unique(kFileSystemUniqueNamePrefix);
+ for (int i = 0; i < kFileSystemUniqueLength; ++i)
+ unique += letters[base::RandInt(0, arraysize(letters) - 2)];
+ return unique;
+}
+
+bool ReadOriginDirectory(const FilePath& base_path,
+ const GURL& origin_url,
+ FilePath* unique) {
+ file_util::FileEnumerator file_enum(
+ base_path, false /* recursive */,
+ file_util::FileEnumerator::DIRECTORIES,
+ FilePath::StringType(kFileSystemUniqueNamePrefix) +
+ FILE_PATH_LITERAL("*"));
+ FilePath current;
+ bool found = false;
+ while (!(current = file_enum.Next()).empty()) {
+ if (current.BaseName().value().length() !=
+ kFileSystemUniqueDirectoryNameLength)
+ continue;
+ if (found) {
+ // TODO(kinuko): Should notify the user to ask for some action.
+ LOG(WARNING) << "Unexpectedly found more than one FileSystem "
+ << "directories for " << origin_url;
+ return false;
+ }
+ found = true;
+ *unique = current;
+ }
+ return !unique->empty();
+}
+
+FilePath GetFileSystemRootPathOnFileThreadHelper(
+ const GURL& origin_url, const FilePath &origin_base_path, bool create) {
+ FilePath root;
+ if (ReadOriginDirectory(origin_base_path, origin_url, &root))
+ return root;
+
+ if (!create)
+ return FilePath();
+
+ // Creates the root directory.
+ root = origin_base_path.Append(CreateUniqueDirectoryName(origin_url));
+ if (!file_util::CreateDirectory(root))
+ return FilePath();
+
+ return root;
+}
+
+} // anonymous namespace
+
+namespace fileapi {
+
+const FilePath::CharType SandboxMountPointProvider::kFileSystemDirectory[] =
+ FILE_PATH_LITERAL("FileSystem");
+
+const char SandboxMountPointProvider::kPersistentName[] = "Persistent";
+const char SandboxMountPointProvider::kTemporaryName[] = "Temporary";
+
+SandboxMountPointProvider::SandboxMountPointProvider(
+ FileSystemPathManager* path_manager,
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ const FilePath& profile_path)
+ : path_manager_(path_manager),
+ file_message_loop_(file_message_loop),
+ base_path_(profile_path.Append(kFileSystemDirectory)) {
+}
+
+bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url) {
+ // We essentially depend on quota to do our access controls.
+ return path_manager_->IsAllowedScheme(origin_url);
+}
+
+class SandboxMountPointProvider::GetFileSystemRootPathTask
+ : public base::RefCountedThreadSafe<
+ SandboxMountPointProvider::GetFileSystemRootPathTask> {
+ public:
+ GetFileSystemRootPathTask(
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ const std::string& name,
+ FileSystemPathManager::GetRootPathCallback* callback)
+ : file_message_loop_(file_message_loop),
+ origin_message_loop_proxy_(
+ base::MessageLoopProxy::CreateForCurrentThread()),
+ name_(name),
+ callback_(callback) {
+ }
+
+ void Start(const GURL& origin_url,
+ const FilePath& origin_base_path,
+ bool create) {
+ file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread,
+ origin_url, origin_base_path, create));
+ }
+
+ private:
+ void GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ const FilePath& origin_base_path,
+ bool create) {
+ DispatchCallbackOnCallerThread(
+ GetFileSystemRootPathOnFileThreadHelper(
+ origin_url, origin_base_path, create));
+ }
+
+ void DispatchCallbackOnCallerThread(const FilePath& root_path) {
+ origin_message_loop_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback,
+ root_path));
+ }
+
+ void DispatchCallback(const FilePath& root_path) {
+ callback_->Run(!root_path.empty(), root_path, name_);
+ callback_.reset();
+ }
+
+ scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+ scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
+ std::string name_;
+ scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_;
+};
+
+bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename)
+ const {
+ if (filename.value().empty())
+ return false;
+
+ if (IsWhitespace(filename.value()[filename.value().size() - 1]) ||
+ filename.value()[filename.value().size() - 1] == '.')
+ return true;
+
+ std::string filename_lower = StringToLowerASCII(
+ FilePathStringToASCII(filename.value()));
+
+ for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
+ // Exact match.
+ if (filename_lower == kRestrictedNames[i])
+ return true;
+ // Starts with "RESTRICTED_NAME.".
+ if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0)
+ return true;
+ }
+
+ for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
+ if (filename.value().find(kRestrictedChars[i]) !=
+ FilePath::StringType::npos)
+ return true;
+ }
+
+ return false;
+}
+
+void SandboxMountPointProvider::GetFileSystemRootPath(
+ const GURL& origin_url, fileapi::FileSystemType type,
+ bool create, FileSystemPathManager::GetRootPathCallback* callback_ptr) {
+ scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback(callback_ptr);
+ std::string name;
+ FilePath origin_base_path;
+
+ if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, &name)) {
+ callback->Run(false, FilePath(), std::string());
+ return;
+ }
+
+ scoped_refptr<GetFileSystemRootPathTask> task(
+ new GetFileSystemRootPathTask(file_message_loop_,
+ name,
+ callback.release()));
+ task->Start(origin_url, origin_base_path, create);
+};
+
+FilePath SandboxMountPointProvider::GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url, FileSystemType type, bool create) {
+ FilePath origin_base_path;
+ if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, NULL)) {
+ return FilePath();
+ }
+ return GetFileSystemRootPathOnFileThreadHelper(
+ origin_url, origin_base_path, create);
+}
+
+// static
+std::string SandboxMountPointProvider::GetOriginIdentifierFromURL(
+ const GURL& url) {
+ WebKit::WebSecurityOrigin web_security_origin =
+ WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
+ return web_security_origin.databaseIdentifier().utf8();
+}
+
+// static
+FilePath SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
+ const FilePath& base_path, const std::string& origin_identifier,
+ fileapi::FileSystemType type) {
+ if (origin_identifier.empty())
+ return FilePath();
+ std::string type_string =
+ FileSystemPathManager::GetFileSystemTypeString(type);
+ if (type_string.empty()) {
+ LOG(WARNING) << "Unknown filesystem type is requested:" << type;
+ return FilePath();
+ }
+ return base_path.AppendASCII(origin_identifier)
+ .AppendASCII(type_string);
+}
+
+SandboxMountPointProvider::OriginEnumerator::OriginEnumerator(
+ const FilePath& base_path)
+ : enumerator_(base_path, false /* recursive */,
+ file_util::FileEnumerator::DIRECTORIES) {
+}
+
+std::string SandboxMountPointProvider::OriginEnumerator::Next() {
+ current_ = enumerator_.Next();
+ return FilePathStringToASCII(current_.BaseName().value());
+}
+
+bool SandboxMountPointProvider::OriginEnumerator::HasTemporary() {
+ return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
+ SandboxMountPointProvider::kTemporaryName));
+}
+
+bool SandboxMountPointProvider::OriginEnumerator::HasPersistent() {
+ return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
+ SandboxMountPointProvider::kPersistentName));
+}
+
+bool SandboxMountPointProvider::GetOriginBasePathAndName(
+ const GURL& origin_url,
+ FilePath* origin_base_path,
+ FileSystemType type,
+ std::string* name) {
+
+ if (path_manager_->is_incognito())
+ // TODO(kinuko): return an isolated temporary directory.
+ return false;
+
+ if (!path_manager_->IsAllowedScheme(origin_url))
+ return false;
+
+ std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
+ *origin_base_path = GetFileSystemBaseDirectoryForOriginAndType(
+ base_path(), origin_identifier, type);
+ if (origin_base_path->empty())
+ return false;
+
+ std::string type_string =
+ FileSystemPathManager::GetFileSystemTypeString(type);
+ DCHECK(!type_string.empty());
+ if (name)
+ *name = origin_identifier + ":" + type_string;
+ return true;
+}
+
+} // namespace fileapi
diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h
new file mode 100644
index 0000000..d981cc8
--- /dev/null
+++ b/webkit/fileapi/sandbox_mount_point_provider.h
@@ -0,0 +1,120 @@
+// 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_FILEAPI_SANDBOX_MOUNT_POINT_PROVIDER_H_
+#define WEBKIT_FILEAPI_SANDBOX_MOUNT_POINT_PROVIDER_H_
+
+#include <string>
+
+#include "base/file_path.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/fileapi/file_system_mount_point_provider.h"
+
+class GURL;
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace fileapi {
+
+class SandboxMountPointProvider : public FileSystemMountPointProvider {
+ public:
+
+ SandboxMountPointProvider(
+ FileSystemPathManager* path_manager,
+ scoped_refptr<base::MessageLoopProxy> file_message_loop,
+ const FilePath& profile_path);
+
+ // Checks if mount point access is allowed from |origin_url|.
+ virtual bool IsAccessAllowed(const GURL& origin_url);
+
+ // Retrieves the root path for the given |origin_url| and |type|, and
+ // calls the given |callback| with the root path and name.
+ // If |create| is true this also creates the directory if it doesn't exist.
+ void GetFileSystemRootPath(
+ const GURL& origin_url,
+ FileSystemType type,
+ bool create,
+ FileSystemPathManager::GetRootPathCallback* callback);
+
+ // Like GetFileSystemRootPath, but synchronous, and can be called only while
+ // running on the file thread.
+ FilePath GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url,
+ FileSystemType type,
+ bool create);
+
+ // The FileSystem directory name.
+ static const FilePath::CharType kFileSystemDirectory[];
+
+ static const char kPersistentName[];
+ static const char kTemporaryName[];
+
+ const FilePath& base_path() const {
+ return base_path_;
+ }
+
+ // Checks if a given |name| contains any restricted names/chars in it.
+ virtual bool IsRestrictedFileName(const FilePath& filename) const;
+
+ // Returns the origin identifier string, which is used as a part of the
+ // sandboxed path component, for the given |url|.
+ static std::string GetOriginIdentifierFromURL(const GURL& url);
+
+ // Gets a base directory path of the sandboxed filesystem that is
+ // specified by |origin_identifier| and |type|.
+ // |base_path| must be pointing the FileSystem's data directory
+ // under the profile directory, i.e. <profile_dir>/kFileSystemDirectory.
+ // Returns an empty path if any of the given parameters are invalid.
+ // Returned directory path does not contain 'unique' part, therefore
+ // it is not an actual root path for the filesystem.
+ static FilePath GetFileSystemBaseDirectoryForOriginAndType(
+ const FilePath& base_path,
+ const std::string& origin_identifier,
+ fileapi::FileSystemType type);
+
+ // Enumerates origins under the given |base_path|.
+ // This must be used on the FILE thread.
+ class OriginEnumerator {
+ public:
+ explicit OriginEnumerator(const FilePath& base_path);
+
+ // Returns the next origin identifier. Returns empty if there are no
+ // more origins.
+ std::string Next();
+
+ bool HasTemporary();
+ bool HasPersistent();
+ const FilePath& path() { return current_; }
+
+ private:
+ file_util::FileEnumerator enumerator_;
+ FilePath current_;
+ };
+
+ private:
+ bool GetOriginBasePathAndName(
+ const GURL& origin_url,
+ FilePath* base_path,
+ FileSystemType type,
+ std::string* name);
+
+ class GetFileSystemRootPathTask;
+
+ // The path_manager_ isn't owned by this instance; this instance is owned by
+ // the path_manager_, and they have the same lifetime.
+ FileSystemPathManager* path_manager_;
+
+ scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+
+ const FilePath base_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(SandboxMountPointProvider);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_SANDBOX_MOUNT_POINT_PROVIDER_H_
+
diff --git a/webkit/fileapi/sandbox_mount_point_provider_unittest.cc b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc
new file mode 100644
index 0000000..f4d12a5f
--- /dev/null
+++ b/webkit/fileapi/sandbox_mount_point_provider_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/ref_counted.h"
+#include "base/scoped_callback_factory.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_temp_dir.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/file_system_util.h"
+
+using namespace fileapi;
+
+class SandboxMountPointProviderOriginEnumeratorTest : public testing::Test {
+ public:
+ void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ enumerator_.reset(new SandboxMountPointProvider::OriginEnumerator(
+ data_dir_.path()));
+ }
+
+ SandboxMountPointProvider::OriginEnumerator* enumerator() const {
+ return enumerator_.get();
+ }
+
+ protected:
+ void CreateOriginTypeDirectory(const std::string& origin_identifier,
+ fileapi::FileSystemType type) {
+ std::string type_string =
+ FileSystemPathManager::GetFileSystemTypeString(type);
+ ASSERT_TRUE(!type_string.empty());
+ FilePath target = data_dir_.path().AppendASCII(origin_identifier)
+ .AppendASCII(type_string);
+ file_util::CreateDirectory(target);
+ ASSERT_TRUE(file_util::DirectoryExists(target));
+ }
+
+ ScopedTempDir data_dir_;
+ scoped_ptr<SandboxMountPointProvider::OriginEnumerator> enumerator_;
+};
+
+TEST_F(SandboxMountPointProviderOriginEnumeratorTest, Empty) {
+ ASSERT_TRUE(enumerator()->Next().empty());
+}
+
+TEST_F(SandboxMountPointProviderOriginEnumeratorTest, EnumerateOrigins) {
+ const char* temporary_origins[] = {
+ "http_www.bar.com_0",
+ "http_www.foo.com_0",
+ "http_www.foo.com_80",
+ "http_www.example.com_8080",
+ "http_www.google.com_80",
+ };
+ const char* persistent_origins[] = {
+ "http_www.bar.com_0",
+ "http_www.foo.com_8080",
+ "http_www.foo.com_80",
+ };
+ size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
+ size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
+ std::set<std::string> temporary_set, persistent_set;
+ for (size_t i = 0; i < temporary_size; ++i) {
+ CreateOriginTypeDirectory(temporary_origins[i],
+ fileapi::kFileSystemTypeTemporary);
+ temporary_set.insert(temporary_origins[i]);
+ }
+ for (size_t i = 0; i < persistent_size; ++i) {
+ CreateOriginTypeDirectory(persistent_origins[i], kFileSystemTypePersistent);
+ persistent_set.insert(persistent_origins[i]);
+ }
+
+ size_t temporary_actual_size = 0;
+ size_t persistent_actual_size = 0;
+ std::string current;
+ while (!(current = enumerator()->Next()).empty()) {
+ SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current);
+ if (enumerator()->HasTemporary()) {
+ ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
+ ++temporary_actual_size;
+ }
+ if (enumerator()->HasPersistent()) {
+ ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
+ ++persistent_actual_size;
+ }
+ }
+
+ ASSERT_EQ(temporary_size, temporary_actual_size);
+ ASSERT_EQ(persistent_size, persistent_actual_size);
+}
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index f1191c6..1b0e127 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -23,8 +23,11 @@
'file_system_file_util.h',
'file_system_file_util_proxy.cc',
'file_system_file_util_proxy.h',
+ 'file_system_mount_point_provider.h',
'file_system_operation.cc',
'file_system_operation.h',
+ 'file_system_operation_context.cc',
+ 'file_system_operation_context.h',
'file_system_path_manager.cc',
'file_system_path_manager.h',
'file_system_types.h',
@@ -38,6 +41,10 @@
'file_system_usage_cache.cc',
'file_writer_delegate.cc',
'file_writer_delegate.h',
+ 'local_file_system_file_util.cc',
+ 'local_file_system_file_util.h',
+ 'sandbox_mount_point_provider.cc',
+ 'sandbox_mount_point_provider.h',
'webfilewriter_base.cc',
'webfilewriter_base.h',
],