diff options
author | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-07 19:55:00 +0000 |
---|---|---|
committer | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-07 19:55:00 +0000 |
commit | 368ddad78d3f2eac1ea7a92cfb9716ecd0166279 (patch) | |
tree | 12991a1cf9204760a254dfacd954158035e4d52b /webkit/fileapi/file_writer_delegate.cc | |
parent | c1973bdf0c94687f96155af8249358a4b585e381 (diff) | |
download | chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.zip chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.tar.gz chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.tar.bz2 |
Add the actual writing-files part of FileWriter.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/3476002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61833 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi/file_writer_delegate.cc')
-rw-r--r-- | webkit/fileapi/file_writer_delegate.cc | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/webkit/fileapi/file_writer_delegate.cc b/webkit/fileapi/file_writer_delegate.cc new file mode 100644 index 0000000..d84d22f32 --- /dev/null +++ b/webkit/fileapi/file_writer_delegate.cc @@ -0,0 +1,164 @@ +// Copyright (c) 2010 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/fileapi/file_writer_delegate.h" + +#include "base/message_loop.h" +#include "net/base/net_errors.h" +#include "webkit/fileapi/file_system_operation.h" + +namespace fileapi { + +static const int kReadBufSize = 32768; + +FileWriterDelegate::FileWriterDelegate( + FileSystemOperation* file_system_operation, + int64 offset) + : file_system_operation_(file_system_operation), + file_(base::kInvalidPlatformFileValue), + offset_(offset), + bytes_read_backlog_(0), + bytes_written_(0), + bytes_read_(0), + io_buffer_(new net::IOBufferWithSize(kReadBufSize)), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +} + +FileWriterDelegate::~FileWriterDelegate() { +} + +void FileWriterDelegate::Start(base::PlatformFile file, URLRequest* request) { + file_ = file; + request_ = request; + file_stream_.reset( + new net::FileStream( + file, + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | + base::PLATFORM_FILE_ASYNC)); + request_->Start(); +} + +void FileWriterDelegate::OnReceivedRedirect( + URLRequest* request, const GURL& new_url, bool* defer_redirect) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnAuthRequired( + URLRequest* request, net::AuthChallengeInfo* auth_info) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnCertificateRequested( + URLRequest* request, net::SSLCertRequestInfo* cert_request_info) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnSSLCertificateError( + URLRequest* request, int cert_error, net::X509Certificate* cert) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnResponseStarted(URLRequest* request) { + DCHECK_EQ(request_, request); + if (!request->status().is_success()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + int64 error = file_stream_->Seek(net::FROM_BEGIN, offset_); + if (error != offset_) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + Read(); +} + +void FileWriterDelegate::OnReadCompleted(URLRequest* request, int bytes_read) { + DCHECK_EQ(request_, request); + if (!request->status().is_success()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + OnDataReceived(bytes_read); +} + +void FileWriterDelegate::Read() { + bytes_written_ = 0; + bytes_read_ = 0; + if (request_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_)) { + MessageLoop::current()->PostTask( + FROM_HERE, + method_factory_.NewRunnableMethod( + &FileWriterDelegate::OnDataReceived, bytes_read_)); + } else if (!request_->status().is_io_pending()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + } +} + +void FileWriterDelegate::OnDataReceived(int bytes_read) { + bytes_read_ = bytes_read; + if (!bytes_read_) { // We're done. + OnProgress(0, true); + } else { + // This could easily be optimized to rotate between a pool of buffers, so + // that we could read and write at the same time. It's not yet clear that + // it's necessary. + Write(); + } +} + +void FileWriterDelegate::Write() { + int write_response = file_stream_->Write( + io_buffer_->data() + bytes_written_, + bytes_read_ - bytes_written_, + callback_factory_.NewCallback(&FileWriterDelegate::OnDataWritten)); + if (write_response > 0) + MessageLoop::current()->PostTask( + FROM_HERE, + method_factory_.NewRunnableMethod( + &FileWriterDelegate::OnDataWritten, write_response)); + else if (net::ERR_IO_PENDING != write_response) + OnError(base::PLATFORM_FILE_ERROR_FAILED); +} + +void FileWriterDelegate::OnDataWritten(int write_response) { + if (write_response > 0) { + OnProgress(write_response, false); + bytes_written_ += write_response; + if (bytes_written_ == bytes_read_) + Read(); + else + Write(); + } else { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + } +} + +void FileWriterDelegate::OnError(base::PlatformFileError error) { + request_->Cancel(); + file_system_operation_->DidWrite(error, 0, true); +} + +void FileWriterDelegate::OnProgress(int bytes_read, bool done) { + DCHECK(bytes_read + bytes_read_backlog_ >= bytes_read_backlog_); + static const int kMinProgressDelayMS = 200; + base::Time currentTime = base::Time::Now(); + if (done || last_progress_event_time_.is_null() || + (currentTime - last_progress_event_time_).InMilliseconds() > + kMinProgressDelayMS) { + file_system_operation_->DidWrite(base::PLATFORM_FILE_OK, + bytes_read + bytes_read_backlog_, done); + last_progress_event_time_ = currentTime; + bytes_read_backlog_ = 0; + } else { + bytes_read_backlog_ += bytes_read; + } +} + +} // namespace fileapi + |