blob: dabe8f18bffefbc733e10c985a1207e6b26894ef [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_
#define STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_
#include <stdint.h>
#include <map>
#include <set>
#include <vector>
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/fileapi/file_system_operation.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/browser/storage_browser_export.h"
namespace net {
class URLRequestContext;
}
namespace storage {
class FileSystemURL;
class FileSystemContext;
// A central interface for running FileSystem API operations.
// All operation methods take callback and returns OperationID, which is
// an integer value which can be used for cancelling an operation.
// All operation methods return kErrorOperationID if running (posting) an
// operation fails, in addition to dispatching the callback with an error
// code (therefore in most cases the caller does not need to check the
// returned operation ID).
class STORAGE_EXPORT FileSystemOperationRunner
: public base::SupportsWeakPtr<FileSystemOperationRunner> {
public:
typedef FileSystemOperation::GetMetadataCallback GetMetadataCallback;
typedef FileSystemOperation::ReadDirectoryCallback ReadDirectoryCallback;
typedef FileSystemOperation::SnapshotFileCallback SnapshotFileCallback;
typedef FileSystemOperation::StatusCallback StatusCallback;
typedef FileSystemOperation::WriteCallback WriteCallback;
typedef FileSystemOperation::OpenFileCallback OpenFileCallback;
typedef FileSystemOperation::ErrorBehavior ErrorBehavior;
typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback;
typedef FileSystemOperation::CopyFileProgressCallback
CopyFileProgressCallback;
typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
typedef FileSystemOperation::GetMetadataField GetMetadataField;
typedef int OperationID;
virtual ~FileSystemOperationRunner();
// Cancels all inflight operations.
void Shutdown();
// Creates a file at |url|. If |exclusive| is true, an error is raised
// in case a file is already present at the URL.
OperationID CreateFile(const FileSystemURL& url,
bool exclusive,
const StatusCallback& callback);
OperationID CreateDirectory(const FileSystemURL& url,
bool exclusive,
bool recursive,
const StatusCallback& callback);
// Copies a file or directory from |src_url| to |dest_url|. If
// |src_url| is a directory, the contents of |src_url| are copied to
// |dest_url| recursively. A new file or directory is created at
// |dest_url| as needed.
// For |option| and |progress_callback|, see file_system_operation.h for
// details.
OperationID Copy(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
CopyOrMoveOption option,
ErrorBehavior error_behavior,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback);
// Moves a file or directory from |src_url| to |dest_url|. A new file
// or directory is created at |dest_url| as needed.
// For |option|, see file_system_operation.h for details.
OperationID Move(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
CopyOrMoveOption option,
const StatusCallback& callback);
// Checks if a directory is present at |url|.
OperationID DirectoryExists(const FileSystemURL& url,
const StatusCallback& callback);
// Checks if a file is present at |url|.
OperationID FileExists(const FileSystemURL& url,
const StatusCallback& callback);
// Gets the metadata of a file or directory at |url|.
OperationID GetMetadata(const FileSystemURL& url,
int fields,
const GetMetadataCallback& callback);
// Reads contents of a directory at |url|.
OperationID ReadDirectory(const FileSystemURL& url,
const ReadDirectoryCallback& callback);
// Removes a file or directory at |url|. If |recursive| is true, remove
// all files and directories under the directory at |url| recursively.
OperationID Remove(const FileSystemURL& url, bool recursive,
const StatusCallback& callback);
// Writes contents of |blob_url| to |url| at |offset|.
// |url_request_context| is used to read contents in |blob|.
OperationID Write(const net::URLRequestContext* url_request_context,
const FileSystemURL& url,
scoped_ptr<storage::BlobDataHandle> blob,
int64_t offset,
const WriteCallback& callback);
// Truncates a file at |url| to |length|. If |length| is larger than
// the original file size, the file will be extended, and the extended
// part is filled with null bytes.
OperationID Truncate(const FileSystemURL& url,
int64_t length,
const StatusCallback& callback);
// Tries to cancel the operation |id| [we support cancelling write or
// truncate only]. Reports failure for the current operation, then reports
// success for the cancel operation itself via the |callback|.
void Cancel(OperationID id, const StatusCallback& callback);
// Modifies timestamps of a file or directory at |url| with
// |last_access_time| and |last_modified_time|. The function DOES NOT
// create a file unlike 'touch' command on Linux.
//
// This function is used only by Pepper as of writing.
OperationID TouchFile(const FileSystemURL& url,
const base::Time& last_access_time,
const base::Time& last_modified_time,
const StatusCallback& callback);
// Opens a file at |url| with |file_flags|, where flags are OR'ed
// values of base::PlatformFileFlags.
//
// |peer_handle| is the process handle of a pepper plugin process, which
// is necessary for underlying IPC calls with Pepper plugins.
//
// This function is used only by Pepper as of writing.
OperationID OpenFile(const FileSystemURL& url,
int file_flags,
const OpenFileCallback& callback);
// Creates a local snapshot file for a given |url| and returns the
// metadata and platform url of the snapshot file via |callback|.
// In local filesystem cases the implementation may simply return
// the metadata of the file itself (as well as GetMetadata does),
// while in remote filesystem case the backend may want to download the file
// into a temporary snapshot file and return the metadata of the
// temporary file. Or if the implementaiton already has the local cache
// data for |url| it can simply return the url to the cache.
OperationID CreateSnapshotFile(const FileSystemURL& url,
const SnapshotFileCallback& callback);
// Copies in a single file from a different filesystem.
//
// This returns:
// - File::FILE_ERROR_NOT_FOUND if |src_file_path|
// or the parent directory of |dest_url| does not exist.
// - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
// is not a file.
// - File::FILE_ERROR_FAILED if |dest_url| does not exist and
// its parent path is a file.
//
OperationID CopyInForeignFile(const base::FilePath& src_local_disk_path,
const FileSystemURL& dest_url,
const StatusCallback& callback);
// Removes a single file.
//
// This returns:
// - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
// - File::FILE_ERROR_NOT_A_FILE if |url| is not a file.
//
OperationID RemoveFile(const FileSystemURL& url,
const StatusCallback& callback);
// Removes a single empty directory.
//
// This returns:
// - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
// - File::FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory.
// - File::FILE_ERROR_NOT_EMPTY if |url| is not empty.
//
OperationID RemoveDirectory(const FileSystemURL& url,
const StatusCallback& callback);
// Copies a file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
// For |option| and |progress_callback|, see file_system_operation.h for
// details.
//
// This returns:
// - File::FILE_ERROR_NOT_FOUND if |src_url|
// or the parent directory of |dest_url| does not exist.
// - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
// - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
// is not a file.
// - File::FILE_ERROR_FAILED if |dest_url| does not exist and
// its parent path is a file.
//
OperationID CopyFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback);
// Moves a local file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
// For |option|, see file_system_operation.h for details.
//
// This returns:
// - File::FILE_ERROR_NOT_FOUND if |src_url|
// or the parent directory of |dest_url| does not exist.
// - File::FILE_ERROR_NOT_A_FILE if |src_url| exists but is not a file.
// - File::FILE_ERROR_INVALID_OPERATION if |dest_url| exists and
// is not a file.
// - File::FILE_ERROR_FAILED if |dest_url| does not exist and
// its parent path is a file.
//
OperationID MoveFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
CopyOrMoveOption option,
const StatusCallback& callback);
// This is called only by pepper plugin as of writing to synchronously get
// the underlying platform path to upload a file in the sandboxed filesystem
// (e.g. TEMPORARY or PERSISTENT).
base::File::Error SyncGetPlatformPath(const FileSystemURL& url,
base::FilePath* platform_path);
private:
class BeginOperationScoper;
struct OperationHandle {
OperationID id;
base::WeakPtr<BeginOperationScoper> scope;
OperationHandle();
~OperationHandle();
};
friend class FileSystemContext;
explicit FileSystemOperationRunner(FileSystemContext* file_system_context);
void DidFinish(const OperationHandle& handle,
const StatusCallback& callback,
base::File::Error rv);
void DidGetMetadata(const OperationHandle& handle,
const GetMetadataCallback& callback,
base::File::Error rv,
const base::File::Info& file_info);
void DidReadDirectory(const OperationHandle& handle,
const ReadDirectoryCallback& callback,
base::File::Error rv,
const std::vector<DirectoryEntry>& entries,
bool has_more);
void DidWrite(const OperationHandle& handle,
const WriteCallback& callback,
base::File::Error rv,
int64_t bytes,
bool complete);
void DidOpenFile(
const OperationHandle& handle,
const OpenFileCallback& callback,
base::File file,
const base::Closure& on_close_callback);
void DidCreateSnapshot(
const OperationHandle& handle,
const SnapshotFileCallback& callback,
base::File::Error rv,
const base::File::Info& file_info,
const base::FilePath& platform_path,
const scoped_refptr<storage::ShareableFileReference>& file_ref);
void OnCopyProgress(const OperationHandle& handle,
const CopyProgressCallback& callback,
FileSystemOperation::CopyProgressType type,
const FileSystemURL& source_url,
const FileSystemURL& dest_url,
int64_t size);
void PrepareForWrite(OperationID id, const FileSystemURL& url);
void PrepareForRead(OperationID id, const FileSystemURL& url);
// These must be called at the beginning and end of any async operations.
OperationHandle BeginOperation(FileSystemOperation* operation,
base::WeakPtr<BeginOperationScoper> scope);
void FinishOperation(OperationID id);
// Not owned; file_system_context owns this.
FileSystemContext* file_system_context_;
// IDMap<FileSystemOperation, IDMapOwnPointer> operations_;
IDMap<FileSystemOperation, IDMapOwnPointer> operations_;
// We keep track of the file to be modified by each operation so that
// we can notify observers when we're done.
typedef std::map<OperationID, FileSystemURLSet> OperationToURLSet;
OperationToURLSet write_target_urls_;
// Operations that are finished but not yet fire their callbacks.
std::set<OperationID> finished_operations_;
// Callbacks for stray cancels whose target operation is already finished.
std::map<OperationID, StatusCallback> stray_cancel_callbacks_;
DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunner);
};
} // namespace storage
#endif // STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_