net cleanup: Remove unnecessary namespace prefixes.
[chromium-blink-merge.git] / storage / browser / fileapi / file_writer_delegate.cc
blobf8b1542b68a75d1e84b6200a022b5c142087eef6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "storage/browser/fileapi/file_writer_delegate.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/files/file_util_proxy.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "net/base/net_errors.h"
15 #include "storage/browser/fileapi/file_stream_writer.h"
16 #include "storage/browser/fileapi/file_system_context.h"
17 #include "storage/common/fileapi/file_system_mount_option.h"
18 #include "storage/common/fileapi/file_system_util.h"
20 namespace storage {
22 static const int kReadBufSize = 32768;
24 FileWriterDelegate::FileWriterDelegate(
25 scoped_ptr<FileStreamWriter> file_stream_writer,
26 FlushPolicy flush_policy)
27 : file_stream_writer_(file_stream_writer.Pass()),
28 writing_started_(false),
29 flush_policy_(flush_policy),
30 bytes_written_backlog_(0),
31 bytes_written_(0),
32 bytes_read_(0),
33 io_buffer_(new net::IOBufferWithSize(kReadBufSize)),
34 weak_factory_(this) {
37 FileWriterDelegate::~FileWriterDelegate() {
40 void FileWriterDelegate::Start(scoped_ptr<net::URLRequest> request,
41 const DelegateWriteCallback& write_callback) {
42 write_callback_ = write_callback;
43 request_ = request.Pass();
44 request_->Start();
47 void FileWriterDelegate::Cancel() {
48 if (request_) {
49 // This halts any callbacks on this delegate.
50 request_->set_delegate(NULL);
51 request_->Cancel();
54 const int status = file_stream_writer_->Cancel(
55 base::Bind(&FileWriterDelegate::OnWriteCancelled,
56 weak_factory_.GetWeakPtr()));
57 // Return true to finish immediately if we have no pending writes.
58 // Otherwise we'll do the final cleanup in the Cancel callback.
59 if (status != net::ERR_IO_PENDING) {
60 write_callback_.Run(base::File::FILE_ERROR_ABORT, 0,
61 GetCompletionStatusOnError());
65 void FileWriterDelegate::OnReceivedRedirect(
66 net::URLRequest* request,
67 const net::RedirectInfo& redirect_info,
68 bool* defer_redirect) {
69 NOTREACHED();
70 OnError(base::File::FILE_ERROR_SECURITY);
73 void FileWriterDelegate::OnAuthRequired(net::URLRequest* request,
74 net::AuthChallengeInfo* auth_info) {
75 NOTREACHED();
76 OnError(base::File::FILE_ERROR_SECURITY);
79 void FileWriterDelegate::OnCertificateRequested(
80 net::URLRequest* request,
81 net::SSLCertRequestInfo* cert_request_info) {
82 NOTREACHED();
83 OnError(base::File::FILE_ERROR_SECURITY);
86 void FileWriterDelegate::OnSSLCertificateError(net::URLRequest* request,
87 const net::SSLInfo& ssl_info,
88 bool fatal) {
89 NOTREACHED();
90 OnError(base::File::FILE_ERROR_SECURITY);
93 void FileWriterDelegate::OnResponseStarted(net::URLRequest* request) {
94 DCHECK_EQ(request_.get(), request);
95 if (!request->status().is_success() || request->GetResponseCode() != 200) {
96 OnError(base::File::FILE_ERROR_FAILED);
97 return;
99 Read();
102 void FileWriterDelegate::OnReadCompleted(net::URLRequest* request,
103 int bytes_read) {
104 DCHECK_EQ(request_.get(), request);
105 if (!request->status().is_success()) {
106 OnError(base::File::FILE_ERROR_FAILED);
107 return;
109 OnDataReceived(bytes_read);
112 void FileWriterDelegate::Read() {
113 bytes_written_ = 0;
114 bytes_read_ = 0;
115 if (request_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_)) {
116 base::MessageLoop::current()->PostTask(
117 FROM_HERE,
118 base::Bind(&FileWriterDelegate::OnDataReceived,
119 weak_factory_.GetWeakPtr(), bytes_read_));
120 } else if (!request_->status().is_io_pending()) {
121 OnError(base::File::FILE_ERROR_FAILED);
125 void FileWriterDelegate::OnDataReceived(int bytes_read) {
126 bytes_read_ = bytes_read;
127 if (!bytes_read_) { // We're done.
128 OnProgress(0, true);
129 } else {
130 // This could easily be optimized to rotate between a pool of buffers, so
131 // that we could read and write at the same time. It's not yet clear that
132 // it's necessary.
133 cursor_ = new net::DrainableIOBuffer(io_buffer_.get(), bytes_read_);
134 Write();
138 void FileWriterDelegate::Write() {
139 writing_started_ = true;
140 int64 bytes_to_write = bytes_read_ - bytes_written_;
141 int write_response =
142 file_stream_writer_->Write(cursor_.get(),
143 static_cast<int>(bytes_to_write),
144 base::Bind(&FileWriterDelegate::OnDataWritten,
145 weak_factory_.GetWeakPtr()));
146 if (write_response > 0) {
147 base::MessageLoop::current()->PostTask(
148 FROM_HERE,
149 base::Bind(&FileWriterDelegate::OnDataWritten,
150 weak_factory_.GetWeakPtr(), write_response));
151 } else if (net::ERR_IO_PENDING != write_response) {
152 OnError(NetErrorToFileError(write_response));
156 void FileWriterDelegate::OnDataWritten(int write_response) {
157 if (write_response > 0) {
158 OnProgress(write_response, false);
159 cursor_->DidConsume(write_response);
160 bytes_written_ += write_response;
161 if (bytes_written_ == bytes_read_)
162 Read();
163 else
164 Write();
165 } else {
166 OnError(NetErrorToFileError(write_response));
170 FileWriterDelegate::WriteProgressStatus
171 FileWriterDelegate::GetCompletionStatusOnError() const {
172 return writing_started_ ? ERROR_WRITE_STARTED : ERROR_WRITE_NOT_STARTED;
175 void FileWriterDelegate::OnError(base::File::Error error) {
176 if (request_) {
177 request_->set_delegate(NULL);
178 request_->Cancel();
181 if (writing_started_)
182 MaybeFlushForCompletion(error, 0, ERROR_WRITE_STARTED);
183 else
184 write_callback_.Run(error, 0, ERROR_WRITE_NOT_STARTED);
187 void FileWriterDelegate::OnProgress(int bytes_written, bool done) {
188 DCHECK(bytes_written + bytes_written_backlog_ >= bytes_written_backlog_);
189 static const int kMinProgressDelayMS = 200;
190 base::Time currentTime = base::Time::Now();
191 if (done || last_progress_event_time_.is_null() ||
192 (currentTime - last_progress_event_time_).InMilliseconds() >
193 kMinProgressDelayMS) {
194 bytes_written += bytes_written_backlog_;
195 last_progress_event_time_ = currentTime;
196 bytes_written_backlog_ = 0;
198 if (done) {
199 MaybeFlushForCompletion(base::File::FILE_OK, bytes_written,
200 SUCCESS_COMPLETED);
201 } else {
202 write_callback_.Run(base::File::FILE_OK, bytes_written,
203 SUCCESS_IO_PENDING);
205 return;
207 bytes_written_backlog_ += bytes_written;
210 void FileWriterDelegate::OnWriteCancelled(int status) {
211 write_callback_.Run(base::File::FILE_ERROR_ABORT, 0,
212 GetCompletionStatusOnError());
215 void FileWriterDelegate::MaybeFlushForCompletion(
216 base::File::Error error,
217 int bytes_written,
218 WriteProgressStatus progress_status) {
219 if (flush_policy_ == FlushPolicy::NO_FLUSH_ON_COMPLETION) {
220 write_callback_.Run(error, bytes_written, progress_status);
221 return;
223 // DCHECK_EQ on enum classes is not supported.
224 DCHECK(flush_policy_ == FlushPolicy::FLUSH_ON_COMPLETION);
226 int flush_error = file_stream_writer_->Flush(
227 base::Bind(&FileWriterDelegate::OnFlushed, weak_factory_.GetWeakPtr(),
228 error, bytes_written, progress_status));
229 if (flush_error != net::ERR_IO_PENDING)
230 OnFlushed(error, bytes_written, progress_status, flush_error);
233 void FileWriterDelegate::OnFlushed(base::File::Error error,
234 int bytes_written,
235 WriteProgressStatus progress_status,
236 int flush_error) {
237 if (error == base::File::FILE_OK && flush_error != net::OK) {
238 // If the Flush introduced an error, overwrite the status.
239 // Otherwise, keep the original error status.
240 error = NetErrorToFileError(flush_error);
241 progress_status = GetCompletionStatusOnError();
243 write_callback_.Run(error, bytes_written, progress_status);
246 } // namespace storage