X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fchrome%2Fbrowser%2Fchromeos%2Ffile_system_provider%2Ffileapi%2Ffile_stream_writer.cc;h=6441cfba5c2f82be4e0fa8550869c4262a2dd097;hb=3545e9f2671f595d2a2f3ee75ca0393b01e35ef6;hp=1a53d0fccb6c99aa8121912bcaddcf7cf5170278;hpb=7d210d4c7e9ba36e635eabc5b5780495f8a63292;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc b/src/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc index 1a53d0f..6441cfb 100644 --- a/src/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc +++ b/src/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc @@ -23,89 +23,144 @@ namespace { void EmptyStatusCallback(base::File::Error /* result */) { } -// Opens a file for writing and calls the completion callback. Must be called -// on UI thread. -void OpenFileOnUIThread( - const fileapi::FileSystemURL& url, - const FileStreamWriter::OpenFileCompletedCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - util::FileSystemURLParser parser(url); - if (!parser.Parse()) { - callback.Run(base::WeakPtr(), - base::FilePath(), - 0 /* file_handle */, - base::File::FILE_ERROR_SECURITY); - return; +} // namespace + +class FileStreamWriter::OperationRunner + : public base::RefCountedThreadSafe { + public: + OperationRunner() : file_handle_(-1) {} + + // Opens a file for writing and calls the completion callback. Must be called + // on UI thread. + void OpenFileOnUIThread( + const storage::FileSystemURL& url, + const storage::AsyncFileUtil::StatusCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + util::FileSystemURLParser parser(url); + if (!parser.Parse()) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, base::File::FILE_ERROR_SECURITY)); + return; + } + + file_system_ = parser.file_system()->GetWeakPtr(); + abort_callback_ = parser.file_system()->OpenFile( + parser.file_path(), + ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE, + base::Bind( + &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback)); } - parser.file_system()->OpenFile( - parser.file_path(), - ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE, - base::Bind( - callback, parser.file_system()->GetWeakPtr(), parser.file_path())); -} + // Closes a file. Ignores result, since outlives the caller. Must be called on + // UI thread. + void CloseFileOnUIThread() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (file_system_.get() && file_handle_ != -1) { + // Closing a file must not be aborted, since we could end up on files + // which are never closed. + file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback)); + } + } -// Forwards results of calling OpenFileOnUIThread back to the IO thread. -void OnOpenFileCompletedOnUIThread( - const FileStreamWriter::OpenFileCompletedCallback& callback, - base::WeakPtr file_system, - const base::FilePath& file_path, - int file_handle, - base::File::Error result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(callback, file_system, file_path, file_handle, result)); -} + // Requests writing bytes to the file. In case of either success or a failure + // |callback| is executed. Must be called on UI thread. + void WriteFileOnUIThread( + scoped_refptr buffer, + int64 offset, + int length, + const storage::AsyncFileUtil::StatusCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // If the file system got unmounted, then abort the writing operation. + if (!file_system_.get()) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, base::File::FILE_ERROR_ABORT)); + return; + } + + abort_callback_ = file_system_->WriteFile( + file_handle_, + buffer.get(), + offset, + length, + base::Bind( + &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback)); + } -// Closes a file. Ignores result, since it is called from a constructor. -// Must be called on UI thread. -void CloseFileOnUIThread(base::WeakPtr file_system, - int file_handle) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (file_system.get()) - file_system->CloseFile(file_handle, base::Bind(&EmptyStatusCallback)); -} + // Aborts the most recent operation (if exists), and calls the callback. + void AbortOnUIThread(const storage::AsyncFileUtil::StatusCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (abort_callback_.is_null()) { + // No operation to be cancelled. At most a callback call, which will be + // discarded. + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + base::Bind(callback, base::File::FILE_OK)); + return; + } + + const ProvidedFileSystemInterface::AbortCallback abort_callback = + abort_callback_; + abort_callback_ = ProvidedFileSystemInterface::AbortCallback(); + abort_callback.Run(base::Bind( + &OperationRunner::OnAbortCompletedOnUIThread, this, callback)); + } -// Requests writing bytes to the file. In case of either success or a failure -// |callback| is executed. Must be called on UI thread. -void WriteFileOnUIThread( - base::WeakPtr file_system, - int file_handle, - scoped_refptr buffer, - int64 offset, - int length, - const fileapi::AsyncFileUtil::StatusCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // If the file system got unmounted, then abort the writing operation. - if (!file_system.get()) { - callback.Run(base::File::FILE_ERROR_ABORT); - return; + private: + friend class base::RefCountedThreadSafe; + + virtual ~OperationRunner() {} + + // Remembers a file handle for further operations and forwards the result to + // the IO thread. + void OnOpenFileCompletedOnUIThread( + const storage::AsyncFileUtil::StatusCallback& callback, + int file_handle, + base::File::Error result) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + file_handle_ = file_handle; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); } - file_system->WriteFile(file_handle, buffer, offset, length, callback); -} + // Forwards a response of writing to a file to the IO thread. + void OnWriteFileCompletedOnUIThread( + const storage::AsyncFileUtil::StatusCallback& callback, + base::File::Error result) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); + } -// Forward the completion callback to IO thread. -void OnWriteFileCompletedOnUIThread( - const fileapi::AsyncFileUtil::StatusCallback& callback, - base::File::Error result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); -} + // Forwards a response of aborting an operation to the IO thread. + void OnAbortCompletedOnUIThread( + const storage::AsyncFileUtil::StatusCallback& callback, + base::File::Error result) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); + } -} // namespace + ProvidedFileSystemInterface::AbortCallback abort_callback_; + base::WeakPtr file_system_; + int file_handle_; + + DISALLOW_COPY_AND_ASSIGN(OperationRunner); +}; -FileStreamWriter::FileStreamWriter(const fileapi::FileSystemURL& url, +FileStreamWriter::FileStreamWriter(const storage::FileSystemURL& url, int64 initial_offset) : url_(url), current_offset_(initial_offset), + runner_(new OperationRunner), state_(NOT_INITIALIZED), - file_handle_(0), weak_ptr_factory_(this) { } @@ -113,33 +168,31 @@ FileStreamWriter::~FileStreamWriter() { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&CloseFileOnUIThread, file_system_, file_handle_)); + base::Bind(&OperationRunner::CloseFileOnUIThread, runner_)); } void FileStreamWriter::Initialize( const base::Closure& pending_closure, const net::CompletionCallback& error_callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_EQ(NOT_INITIALIZED, state_); state_ = INITIALIZING; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&OpenFileOnUIThread, + base::Bind(&OperationRunner::OpenFileOnUIThread, + runner_, url_, - base::Bind(&OnOpenFileCompletedOnUIThread, - base::Bind(&FileStreamWriter::OnOpenFileCompleted, - weak_ptr_factory_.GetWeakPtr(), - pending_closure, - error_callback)))); + base::Bind(&FileStreamWriter::OnOpenFileCompleted, + weak_ptr_factory_.GetWeakPtr(), + pending_closure, + error_callback))); } void FileStreamWriter::OnOpenFileCompleted( const base::Closure& pending_closure, const net::CompletionCallback& error_callback, - base::WeakPtr file_system, - const base::FilePath& file_path, - int file_handle, base::File::Error result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_EQ(INITIALIZING, state_); @@ -152,10 +205,6 @@ void FileStreamWriter::OnOpenFileCompleted( return; } - file_system_ = file_system; - file_path_ = file_path; - file_handle_ = file_handle; - DCHECK_LT(0, file_handle); DCHECK_EQ(base::File::FILE_OK, result); state_ = INITIALIZED; @@ -209,8 +258,17 @@ int FileStreamWriter::Write(net::IOBuffer* buffer, } int FileStreamWriter::Cancel(const net::CompletionCallback& callback) { - NOTIMPLEMENTED(); - return net::ERR_FAILED; + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&OperationRunner::AbortOnUIThread, + runner_, + base::Bind(&FileStreamWriter::OnAbortCompleted, + weak_ptr_factory_.GetWeakPtr(), + callback))); + return net::ERR_IO_PENDING; } int FileStreamWriter::Flush(const net::CompletionCallback& callback) { @@ -245,6 +303,16 @@ void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback, "file_system_provider", "FileStreamWriter::Write", this); } +void FileStreamWriter::OnAbortCompleted(const net::CompletionCallback& callback, + base::File::Error result) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (result != base::File::FILE_OK) + state_ = FAILED; + + callback.Run(net::FileErrorToNetError(result)); +} + void FileStreamWriter::WriteAfterInitialized( scoped_refptr buffer, int buffer_length, @@ -255,17 +323,15 @@ void FileStreamWriter::WriteAfterInitialized( BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&WriteFileOnUIThread, - file_system_, - file_handle_, + base::Bind(&OperationRunner::WriteFileOnUIThread, + runner_, buffer, current_offset_, buffer_length, - base::Bind(&OnWriteFileCompletedOnUIThread, - base::Bind(&FileStreamWriter::OnWriteFileCompleted, - weak_ptr_factory_.GetWeakPtr(), - buffer_length, - callback)))); + base::Bind(&FileStreamWriter::OnWriteFileCompleted, + weak_ptr_factory_.GetWeakPtr(), + buffer_length, + callback))); } } // namespace file_system_provider