| // 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. |
| |
| #include "webkit/chromeos/fileapi/remote_file_stream_writer.h" |
| |
| #include "net/base/io_buffer.h" |
| #include "net/base/net_errors.h" |
| #include "webkit/blob/local_file_stream_reader.h" |
| #include "webkit/blob/shareable_file_reference.h" |
| #include "webkit/chromeos/fileapi/remote_file_system_proxy.h" |
| #include "webkit/fileapi/local_file_stream_writer.h" |
| |
| namespace fileapi { |
| |
| RemoteFileStreamWriter::RemoteFileStreamWriter( |
| const scoped_refptr<RemoteFileSystemProxyInterface>& remote_filesystem, |
| const FileSystemURL& url, |
| int64 offset) |
| : remote_filesystem_(remote_filesystem), |
| url_(url), |
| initial_offset_(offset), |
| has_pending_create_snapshot_(false), |
| weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| } |
| |
| RemoteFileStreamWriter::~RemoteFileStreamWriter() { |
| } |
| |
| int RemoteFileStreamWriter::Write(net::IOBuffer* buf, |
| int buf_len, |
| const net::CompletionCallback& callback) { |
| DCHECK(!has_pending_create_snapshot_); |
| DCHECK(pending_cancel_callback_.is_null()); |
| |
| if (!local_file_writer_.get()) { |
| has_pending_create_snapshot_ = true; |
| // In this RemoteFileStreamWriter, we only create snapshot file and don't |
| // have explicit close operation. This is ok, because close is automatically |
| // triggered by a refcounted |file_ref_| passed to OnFileOpened, from the |
| // destructor of RemoteFileStreamWriter. |
| remote_filesystem_->CreateWritableSnapshotFile( |
| url_, |
| base::Bind(&RemoteFileStreamWriter::OnFileOpened, |
| weak_factory_.GetWeakPtr(), |
| make_scoped_refptr(buf), |
| buf_len, |
| callback)); |
| return net::ERR_IO_PENDING; |
| } |
| return local_file_writer_->Write(buf, buf_len, callback); |
| } |
| |
| void RemoteFileStreamWriter::OnFileOpened( |
| net::IOBuffer* buf, |
| int buf_len, |
| const net::CompletionCallback& callback, |
| base::PlatformFileError open_result, |
| const FilePath& local_path, |
| const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
| has_pending_create_snapshot_ = false; |
| if (!pending_cancel_callback_.is_null()) { |
| InvokePendingCancelCallback(net::OK); |
| return; |
| } |
| |
| if (open_result != base::PLATFORM_FILE_OK) { |
| callback.Run(net::PlatformFileErrorToNetError(open_result)); |
| return; |
| } |
| |
| // Hold the reference to the file. Releasing the reference notifies the file |
| // system about to close file. |
| file_ref_ = file_ref; |
| |
| DCHECK(!local_file_writer_.get()); |
| local_file_writer_.reset(new fileapi::LocalFileStreamWriter(local_path, |
| initial_offset_)); |
| int result = local_file_writer_->Write(buf, buf_len, callback); |
| if (result != net::ERR_IO_PENDING) |
| callback.Run(result); |
| } |
| |
| int RemoteFileStreamWriter::Cancel(const net::CompletionCallback& callback) { |
| DCHECK(!callback.is_null()); |
| DCHECK(pending_cancel_callback_.is_null()); |
| |
| // If file open operation is in-flight, wait for its completion and cancel |
| // further write operation in OnFileOpened. |
| if (has_pending_create_snapshot_) { |
| pending_cancel_callback_ = callback; |
| return net::ERR_IO_PENDING; |
| } |
| |
| // If LocalFileWriter is already created, just delegate the cancel to it. |
| if (local_file_writer_.get()) { |
| pending_cancel_callback_ = callback; |
| return local_file_writer_->Cancel( |
| base::Bind(&RemoteFileStreamWriter::InvokePendingCancelCallback, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| // Write() is not called yet. |
| return net::ERR_UNEXPECTED; |
| } |
| |
| void RemoteFileStreamWriter::InvokePendingCancelCallback(int result) { |
| net::CompletionCallback callback = pending_cancel_callback_; |
| pending_cancel_callback_.Reset(); |
| callback.Run(result); |
| } |
| |
| } // namespace gdata |