Chromium Code Reviews| Index: webkit/fileapi/file_system_operation.cc |
| =================================================================== |
| --- webkit/fileapi/file_system_operation.cc (revision 77587) |
| +++ webkit/fileapi/file_system_operation.cc (working copy) |
| @@ -11,7 +11,9 @@ |
| #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 { |
| @@ -21,8 +23,8 @@ |
| FileSystemContext* file_system_context) |
| : proxy_(proxy), |
| dispatcher_(dispatcher), |
| - file_system_context_(file_system_context), |
| - file_system_operation_context_(FileSystemFileUtil::GetInstance()), |
| + file_system_operation_context_(file_system_context, |
| + LocalFileSystemFileUtil::GetInstance()), |
| callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| DCHECK(dispatcher); |
| #ifndef NDEBUG |
| @@ -45,8 +47,16 @@ |
| 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 +67,19 @@ |
| 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 +91,20 @@ |
| 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 +114,37 @@ |
| DCHECK(kOperationNone == pending_operation_); |
| pending_operation_ = kOperationCopy; |
| #endif |
| + 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) || |
| - !VerifyFileSystemPathForWrite(dest_path, true /* create */)) { |
| + 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 +153,35 @@ |
| DCHECK(kOperationNone == pending_operation_); |
| pending_operation_ = kOperationMove; |
| #endif |
| + 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) || |
| - !VerifyFileSystemPathForWrite(dest_path, true /* create */)) { |
| + 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)) { |
|
kinuko
2011/03/14 11:03:57
I think we should send back an error (security err
ericu
2011/03/15 02:43:11
That's already done inside the VerifyFileSystemPat
kinuko
2011/03/16 19:33:38
Oh, you're right..
|
| 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 +190,18 @@ |
| 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 +211,18 @@ |
| 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 +232,18 @@ |
| 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 +253,18 @@ |
| 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 +274,19 @@ |
| 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 +299,16 @@ |
| 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 +317,7 @@ |
| 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 +329,19 @@ |
| 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 +353,19 @@ |
| 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 +405,13 @@ |
| 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) |
| + result = FilePath().AppendASCII( |
| + file_system_operation_context_.src_root_url().spec()); |
| + dispatcher_->DidOpenFileSystem(name, result); |
| delete this; |
| } |
| @@ -416,15 +527,21 @@ |
| } |
| 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 +549,35 @@ |
| } |
| bool FileSystemOperation::VerifyFileSystemPathForWrite( |
| - const FilePath& path, bool create) { |
| - GURL origin_url; |
| - FilePath virtual_path; |
| + const FilePath& path, bool create, GURL* origin_url, FileSystemType* type, |
| + FilePath* virtual_path) { |
| - // If we have no context, we just allow any operations. |
| - if (!file_system_context_.get()) |
| + // 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; |
| } |