blob: 5c05c977522ab8e7025cb5dc4cd137fff5ac719f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_
#define WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_
#include <string>
#include <vector>
#include "base/file_path.h"
#include "base/file_util_proxy.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/platform_file.h"
#include "base/process.h"
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_operation_interface.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/quota/quota_manager.h"
namespace base {
class Time;
}
namespace chromeos {
class CrosMountPointProvider;
}
namespace net {
class URLRequest;
class URLRequestContext;
} // namespace net
class GURL;
namespace fileapi {
class FileSystemContext;
class FileWriterDelegate;
class FileSystemOperationTest;
// FileSystemOperation implementation for local file systems.
class FileSystemOperation : public FileSystemOperationInterface {
public:
virtual ~FileSystemOperation();
// FileSystemOperation overrides.
virtual void CreateFile(const GURL& path,
bool exclusive,
const StatusCallback& callback) OVERRIDE;
virtual void CreateDirectory(const GURL& path,
bool exclusive,
bool recursive,
const StatusCallback& callback) OVERRIDE;
virtual void Copy(const GURL& src_path,
const GURL& dest_path,
const StatusCallback& callback) OVERRIDE;
virtual void Move(const GURL& src_path,
const GURL& dest_path,
const StatusCallback& callback) OVERRIDE;
virtual void DirectoryExists(const GURL& path,
const StatusCallback& callback) OVERRIDE;
virtual void FileExists(const GURL& path,
const StatusCallback& callback) OVERRIDE;
virtual void GetMetadata(const GURL& path,
const GetMetadataCallback& callback) OVERRIDE;
virtual void ReadDirectory(const GURL& path,
const ReadDirectoryCallback& callback) OVERRIDE;
virtual void Remove(const GURL& path, bool recursive,
const StatusCallback& callback) OVERRIDE;
virtual void Write(const net::URLRequestContext* url_request_context,
const GURL& path,
const GURL& blob_url,
int64 offset,
const WriteCallback& callback) OVERRIDE;
virtual void Truncate(const GURL& path, int64 length,
const StatusCallback& callback) OVERRIDE;
virtual void TouchFile(const GURL& path,
const base::Time& last_access_time,
const base::Time& last_modified_time,
const StatusCallback& callback) OVERRIDE;
virtual void OpenFile(const GURL& path,
int file_flags,
base::ProcessHandle peer_handle,
const OpenFileCallback& callback) OVERRIDE;
virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE;
virtual FileSystemOperation* AsFileSystemOperation() OVERRIDE;
// Synchronously gets the platform path for the given |path|.
void SyncGetPlatformPath(const GURL& path, FilePath* platform_path);
protected:
class ScopedQuotaUtilHelper;
// Only MountPointProviders or testing class can create a
// new operation directly.
friend class SandboxMountPointProvider;
friend class FileSystemTestHelper;
friend class chromeos::CrosMountPointProvider;
FileSystemOperation(scoped_refptr<base::MessageLoopProxy> proxy,
FileSystemContext* file_system_context);
FileSystemContext* file_system_context() const {
return operation_context_.file_system_context();
}
FileSystemOperationContext* file_system_operation_context() {
return &operation_context_;
}
friend class FileSystemOperationTest;
friend class FileSystemOperationWriteTest;
friend class FileWriterDelegateTest;
friend class FileSystemTestOriginHelper;
friend class FileSystemQuotaTest;
// The unit tests that need to specify and control the lifetime of the
// file_util on their own should call this before performing the actual
// operation. If it is given it will not be overwritten by the class.
void set_override_file_util(FileSystemFileUtil* file_util) {
operation_context_.set_src_file_util(file_util);
operation_context_.set_dest_file_util(file_util);
}
void GetUsageAndQuotaThenCallback(
const GURL& origin_url,
const quota::QuotaManager::GetUsageAndQuotaCallback& callback);
void DelayedCreateFileForQuota(const StatusCallback& callback,
bool exclusive,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedCreateDirectoryForQuota(const StatusCallback& callback,
bool exclusive, bool recursive,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedCopyForQuota(const StatusCallback& callback,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedMoveForQuota(const StatusCallback& callback,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedWriteForQuota(quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedTruncateForQuota(const StatusCallback& callback,
int64 length,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
void DelayedOpenFileForQuota(const OpenFileCallback& callback,
int file_flags,
quota::QuotaStatusCode status,
int64 usage, int64 quota);
// Callback for CreateFile for |exclusive|=true cases.
void DidEnsureFileExistsExclusive(const StatusCallback& callback,
base::PlatformFileError rv,
bool created);
// Callback for CreateFile for |exclusive|=false cases.
void DidEnsureFileExistsNonExclusive(const StatusCallback& callback,
base::PlatformFileError rv,
bool created);
// Generic callback that translates platform errors to WebKit error codes.
void DidFinishFileOperation(const StatusCallback& callback,
base::PlatformFileError rv);
void DidDirectoryExists(const StatusCallback& callback,
base::PlatformFileError rv,
const base::PlatformFileInfo& file_info,
const FilePath& unused);
void DidFileExists(const StatusCallback& callback,
base::PlatformFileError rv,
const base::PlatformFileInfo& file_info,
const FilePath& unused);
void DidGetMetadata(const GetMetadataCallback& callback,
base::PlatformFileError rv,
const base::PlatformFileInfo& file_info,
const FilePath& platform_path);
void DidReadDirectory(
const ReadDirectoryCallback& callback,
base::PlatformFileError rv,
const std::vector<base::FileUtilProxy::Entry>& entries,
bool has_more);
void DidWrite(base::PlatformFileError rv,
int64 bytes,
bool complete);
void DidTouchFile(const StatusCallback& callback,
base::PlatformFileError rv);
void DidOpenFile(const OpenFileCallback& callback,
base::PlatformFileError rv,
base::PassPlatformFile file,
bool created);
// Helper for Write().
void OnFileOpenedForWrite(base::PlatformFileError rv,
base::PassPlatformFile file,
bool created);
// Checks the validity of a given |path| for reading, cracks the path into
// root URL and virtual path components, and returns the correct
// FileSystemFileUtil subclass for this type.
// 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.)
base::PlatformFileError VerifyFileSystemPathForRead(
const GURL& path,
GURL* root_url,
FileSystemType* type,
FilePath* virtual_path,
FileSystemFileUtil** file_util);
// Checks the validity of a given |path| for writing, cracks the path into
// root URL and virtual path components, and returns the correct
// FileSystemFileUtil subclass for this type.
// 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
// PLATFORM_FILE_ERROR_SECURITY if the path is not valid for writing,
// or with PLATFORM_FILE_ERROR_NO_SPACE if the origin is not allowed to
// write to the storage.
// In either case it returns false after firing DidFail.
// If |create| flag is true this also checks if the |path| contains
// any restricted names and chars. If it does, the call fires dispatcher's
// DidFail 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.)
base::PlatformFileError VerifyFileSystemPathForWrite(
const GURL& path,
bool create,
GURL* root_url,
FileSystemType* type,
FilePath* virtual_path,
FileSystemFileUtil** file_util);
// Common internal routine for VerifyFileSystemPathFor{Read,Write}.
base::PlatformFileError VerifyFileSystemPath(const GURL& path,
GURL* root_url,
FileSystemType* type,
FilePath* virtual_path,
FileSystemFileUtil** file_util);
// Setup*Context*() functions will call the appropriate VerifyFileSystem
// function and store the results to operation_context_ and
// *_virtual_path_.
// Return the result of VerifyFileSystem*().
base::PlatformFileError SetupSrcContextForRead(const GURL& path);
base::PlatformFileError SetupSrcContextForWrite(const GURL& path,
bool create);
base::PlatformFileError SetupDestContextForWrite(const GURL& path,
bool create);
// Used only for internal assertions.
// Returns false if there's another inflight pending operation.
bool SetPendingOperationType(OperationType type);
// Proxy for calling file_util_proxy methods.
scoped_refptr<base::MessageLoopProxy> proxy_;
FileSystemOperationContext operation_context_;
scoped_ptr<ScopedQuotaUtilHelper> quota_util_helper_;
// These are all used only by Write().
friend class FileWriterDelegate;
scoped_ptr<FileWriterDelegate> file_writer_delegate_;
scoped_ptr<net::URLRequest> blob_request_;
// write_callback is kept in this class for so that we can dispatch it when
// the operation is cancelled. calcel_callback is kept for canceling a
// Truncate() operation. We can't actually stop Truncate in another thread;
// after it resumed from the working thread, cancellation takes place.
WriteCallback write_callback_;
StatusCallback cancel_callback_;
void set_write_callback(const WriteCallback& write_callback) {
write_callback_ = write_callback;
}
// Used only by OpenFile, in order to clone the file handle back to the
// requesting process.
base::ProcessHandle peer_handle_;
// Used to keep a virtual path around while we check for quota.
// If an operation needs only one path, use src_virtual_path_, even if it's a
// write.
FilePath src_virtual_path_;
FilePath dest_virtual_path_;
// A flag to make sure we call operation only once per instance.
OperationType pending_operation_;
DISALLOW_COPY_AND_ASSIGN(FileSystemOperation);
};
} // namespace fileapi
#endif // WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_