cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / net / base / upload_file_element_reader.cc
blobd1f2a12ac8cd13c6d5037032f13cdd98baf2ea03
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 "net/base/upload_file_element_reader.h"
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/location.h"
10 #include "base/task_runner_util.h"
11 #include "net/base/file_stream.h"
12 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h"
15 namespace net {
17 namespace {
19 // In tests, this value is used to override the return value of
20 // UploadFileElementReader::GetContentLength() when set to non-zero.
21 uint64 overriding_content_length = 0;
23 // This function is used to implement Init().
24 template<typename FileStreamDeleter>
25 int InitInternal(const base::FilePath& path,
26 uint64 range_offset,
27 uint64 range_length,
28 const base::Time& expected_modification_time,
29 scoped_ptr<FileStream, FileStreamDeleter>* out_file_stream,
30 uint64* out_content_length) {
31 scoped_ptr<FileStream> file_stream(new FileStream(NULL));
32 int64 rv = file_stream->OpenSync(
33 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
34 if (rv != OK) {
35 // If the file can't be opened, we'll just upload an empty file.
36 DLOG(WARNING) << "Failed to open \"" << path.value()
37 << "\" for reading: " << rv;
38 file_stream.reset();
39 } else if (range_offset) {
40 rv = file_stream->SeekSync(FROM_BEGIN, range_offset);
41 if (rv < 0) {
42 DLOG(WARNING) << "Failed to seek \"" << path.value()
43 << "\" to offset: " << range_offset << " (" << rv << ")";
44 file_stream.reset();
48 int64 length = 0;
49 if (file_stream.get() &&
50 file_util::GetFileSize(path, &length) &&
51 range_offset < static_cast<uint64>(length)) {
52 // Compensate for the offset.
53 length = std::min(length - range_offset, range_length);
55 *out_content_length = length;
56 out_file_stream->reset(file_stream.release());
58 // If the underlying file has been changed and the expected file modification
59 // time is set, treat it as error. Note that the expected modification time
60 // from WebKit is based on time_t precision. So we have to convert both to
61 // time_t to compare. This check is used for sliced files.
62 if (!expected_modification_time.is_null()) {
63 base::PlatformFileInfo info;
64 if (file_util::GetFileInfo(path, &info) &&
65 expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
66 return ERR_UPLOAD_FILE_CHANGED;
70 return OK;
73 // This function is used to implement Read().
74 int ReadInternal(scoped_refptr<IOBuffer> buf,
75 int buf_length,
76 uint64 bytes_remaining,
77 FileStream* file_stream) {
78 DCHECK_LT(0, buf_length);
80 const uint64 num_bytes_to_read =
81 std::min(bytes_remaining, static_cast<uint64>(buf_length));
83 int result = 0;
84 if (num_bytes_to_read > 0) {
85 DCHECK(file_stream); // file_stream is non-null if content_length_ > 0.
86 result = file_stream->ReadSync(buf->data(), num_bytes_to_read);
87 if (result == 0) // Reached end-of-file earlier than expected.
88 result = ERR_UPLOAD_FILE_CHANGED;
90 return result;
93 } // namespace
95 UploadFileElementReader::FileStreamDeleter::FileStreamDeleter(
96 base::TaskRunner* task_runner) : task_runner_(task_runner) {
97 DCHECK(task_runner_.get());
100 UploadFileElementReader::FileStreamDeleter::~FileStreamDeleter() {}
102 void UploadFileElementReader::FileStreamDeleter::operator() (
103 FileStream* file_stream) const {
104 if (file_stream) {
105 task_runner_->PostTask(FROM_HERE,
106 base::Bind(&base::DeletePointer<FileStream>,
107 file_stream));
111 UploadFileElementReader::UploadFileElementReader(
112 base::TaskRunner* task_runner,
113 const base::FilePath& path,
114 uint64 range_offset,
115 uint64 range_length,
116 const base::Time& expected_modification_time)
117 : task_runner_(task_runner),
118 path_(path),
119 range_offset_(range_offset),
120 range_length_(range_length),
121 expected_modification_time_(expected_modification_time),
122 file_stream_(NULL, FileStreamDeleter(task_runner_.get())),
123 content_length_(0),
124 bytes_remaining_(0),
125 weak_ptr_factory_(this) {
126 DCHECK(task_runner_.get());
129 UploadFileElementReader::~UploadFileElementReader() {
132 const UploadFileElementReader* UploadFileElementReader::AsFileReader() const {
133 return this;
136 int UploadFileElementReader::Init(const CompletionCallback& callback) {
137 DCHECK(!callback.is_null());
138 Reset();
140 ScopedFileStreamPtr* file_stream =
141 new ScopedFileStreamPtr(NULL, FileStreamDeleter(task_runner_.get()));
142 uint64* content_length = new uint64;
143 const bool posted = base::PostTaskAndReplyWithResult(
144 task_runner_.get(),
145 FROM_HERE,
146 base::Bind(&InitInternal<FileStreamDeleter>,
147 path_,
148 range_offset_,
149 range_length_,
150 expected_modification_time_,
151 file_stream,
152 content_length),
153 base::Bind(&UploadFileElementReader::OnInitCompleted,
154 weak_ptr_factory_.GetWeakPtr(),
155 base::Owned(file_stream),
156 base::Owned(content_length),
157 callback));
158 DCHECK(posted);
159 return ERR_IO_PENDING;
162 uint64 UploadFileElementReader::GetContentLength() const {
163 if (overriding_content_length)
164 return overriding_content_length;
165 return content_length_;
168 uint64 UploadFileElementReader::BytesRemaining() const {
169 return bytes_remaining_;
172 int UploadFileElementReader::Read(IOBuffer* buf,
173 int buf_length,
174 const CompletionCallback& callback) {
175 DCHECK(!callback.is_null());
177 if (BytesRemaining() == 0)
178 return 0;
180 // Save the value of file_stream_.get() before base::Passed() invalidates it.
181 FileStream* file_stream_ptr = file_stream_.get();
182 // Pass the ownership of file_stream_ to the worker pool to safely perform
183 // operation even when |this| is destructed before the read completes.
184 const bool posted = base::PostTaskAndReplyWithResult(
185 task_runner_.get(),
186 FROM_HERE,
187 base::Bind(&ReadInternal,
188 scoped_refptr<IOBuffer>(buf),
189 buf_length,
190 BytesRemaining(),
191 file_stream_ptr),
192 base::Bind(&UploadFileElementReader::OnReadCompleted,
193 weak_ptr_factory_.GetWeakPtr(),
194 base::Passed(&file_stream_),
195 callback));
196 DCHECK(posted);
197 return ERR_IO_PENDING;
200 void UploadFileElementReader::Reset() {
201 weak_ptr_factory_.InvalidateWeakPtrs();
202 bytes_remaining_ = 0;
203 content_length_ = 0;
204 file_stream_.reset();
207 void UploadFileElementReader::OnInitCompleted(
208 ScopedFileStreamPtr* file_stream,
209 uint64* content_length,
210 const CompletionCallback& callback,
211 int result) {
212 file_stream_.swap(*file_stream);
213 content_length_ = *content_length;
214 bytes_remaining_ = GetContentLength();
215 if (!callback.is_null())
216 callback.Run(result);
219 void UploadFileElementReader::OnReadCompleted(
220 ScopedFileStreamPtr file_stream,
221 const CompletionCallback& callback,
222 int result) {
223 file_stream_.swap(file_stream);
224 if (result > 0) {
225 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result));
226 bytes_remaining_ -= result;
228 if (!callback.is_null())
229 callback.Run(result);
232 UploadFileElementReader::ScopedOverridingContentLengthForTests::
233 ScopedOverridingContentLengthForTests(uint64 value) {
234 overriding_content_length = value;
237 UploadFileElementReader::ScopedOverridingContentLengthForTests::
238 ~ScopedOverridingContentLengthForTests() {
239 overriding_content_length = 0;
242 UploadFileElementReaderSync::UploadFileElementReaderSync(
243 const base::FilePath& path,
244 uint64 range_offset,
245 uint64 range_length,
246 const base::Time& expected_modification_time)
247 : path_(path),
248 range_offset_(range_offset),
249 range_length_(range_length),
250 expected_modification_time_(expected_modification_time),
251 content_length_(0),
252 bytes_remaining_(0) {
255 UploadFileElementReaderSync::~UploadFileElementReaderSync() {
258 int UploadFileElementReaderSync::Init(const CompletionCallback& callback) {
259 bytes_remaining_ = 0;
260 content_length_ = 0;
261 file_stream_.reset();
263 const int result = InitInternal(path_, range_offset_, range_length_,
264 expected_modification_time_,
265 &file_stream_, &content_length_);
266 bytes_remaining_ = GetContentLength();
267 return result;
270 uint64 UploadFileElementReaderSync::GetContentLength() const {
271 return content_length_;
274 uint64 UploadFileElementReaderSync::BytesRemaining() const {
275 return bytes_remaining_;
278 int UploadFileElementReaderSync::Read(IOBuffer* buf,
279 int buf_length,
280 const CompletionCallback& callback) {
281 const int result = ReadInternal(buf, buf_length, BytesRemaining(),
282 file_stream_.get());
283 if (result > 0) {
284 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result));
285 bytes_remaining_ -= result;
287 return result;
290 } // namespace net