// 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_url, bool exclusive, const StatusCallback& callback) OVERRIDE; virtual void CreateDirectory(const GURL& path_url, bool exclusive, bool recursive, const StatusCallback& callback) OVERRIDE; virtual void Copy(const GURL& src_path_url, const GURL& dest_path_url, const StatusCallback& callback) OVERRIDE; virtual void Move(const GURL& src_path_url, const GURL& dest_path_url, const StatusCallback& callback) OVERRIDE; virtual void DirectoryExists(const GURL& path_url, const StatusCallback& callback) OVERRIDE; virtual void FileExists(const GURL& path_url, const StatusCallback& callback) OVERRIDE; virtual void GetMetadata(const GURL& path_url, const GetMetadataCallback& callback) OVERRIDE; virtual void ReadDirectory(const GURL& path_url, const ReadDirectoryCallback& callback) OVERRIDE; virtual void Remove(const GURL& path_url, bool recursive, const StatusCallback& callback) OVERRIDE; virtual void Write(const net::URLRequestContext* url_request_context, const GURL& path_url, const GURL& blob_url, int64 offset, const WriteCallback& callback) OVERRIDE; virtual void Truncate(const GURL& path_url, int64 length, const StatusCallback& callback) OVERRIDE; virtual void TouchFile(const GURL& path_url, const base::Time& last_access_time, const base::Time& last_modified_time, const StatusCallback& callback) OVERRIDE; virtual void OpenFile(const GURL& path_url, 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_url|. void SyncGetPlatformPath(const GURL& path_url, FilePath* platform_path); protected: class ScopedQuotaNotifier; // Modes for SetUpFileSystemPath. enum SetUpPathMode { PATH_FOR_READ, PATH_FOR_WRITE, PATH_FOR_CREATE, }; // Only MountPointProviders or testing class can create a // new operation directly. friend class SandboxMountPointProvider; friend class FileSystemTestHelper; friend class chromeos::CrosMountPointProvider; friend class FileSystemOperationTest; friend class FileSystemOperationWriteTest; friend class FileWriterDelegateTest; friend class FileSystemTestOriginHelper; friend class FileSystemQuotaTest; 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_; } // 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) { src_util_ = file_util; dest_util_ = file_util; } void GetUsageAndQuotaThenCallback( const GURL& origin, FileSystemType type, const quota::QuotaManager::GetUsageAndQuotaCallback& callback); // Callbacks to perform the actual work after quota check. 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_url| and and populates // |path| and |file_util| for |mode|. base::PlatformFileError SetUpFileSystemPath( const GURL& path_url, FileSystemPath* file_system_path, FileSystemFileUtil** file_util, SetUpPathMode mode); // 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_; FileSystemPath src_path_; FileSystemPath dest_path_; FileSystemFileUtil* src_util_; // Not owned. FileSystemFileUtil* dest_util_; // Not owned. // This is set before any write operations. The destructor of // ScopedQuotaNotifier sends notification to the QuotaManager // to tell the update is done; so that we can make sure notify // the manager after any write operations are done. scoped_ptr<ScopedQuotaNotifier> scoped_quota_notifier_; // 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_; // 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_