move SK_DISABLE_DITHER_32BIT_GRADIENT from SkUserConfig.h to skia.gyp, so we can...
[chromium-blink-merge.git] / net / base / upload_file_element_reader.cc
blob5658f219759bc8d7c5e4e9924bcae235037650f6
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 "base/threading/worker_pool.h"
12 #include "net/base/file_stream.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
16 namespace net {
18 namespace {
20 // In tests, this value is used to override the return value of
21 // UploadFileElementReader::GetContentLength() when set to non-zero.
22 uint64 overriding_content_length = 0;
24 // This function is used to implement Init().
25 int InitInternal(const FilePath& path,
26 uint64 range_offset,
27 uint64 range_length,
28 const base::Time& expected_modification_time,
29 UploadFileElementReader::ScopedFileStreamPtr* 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 if (num_bytes_to_read > 0) {
84 int num_bytes_consumed = 0;
85 // file_stream is NULL if the target file is missing or not readable.
86 if (file_stream) {
87 num_bytes_consumed = file_stream->ReadSync(buf->data(),
88 num_bytes_to_read);
90 if (num_bytes_consumed <= 0) {
91 // If there's less data to read than we initially observed, then
92 // pad with zero. Otherwise the server will hang waiting for the
93 // rest of the data.
94 memset(buf->data(), 0, num_bytes_to_read);
97 return num_bytes_to_read;
100 } // namespace
102 void UploadFileElementReader::FileStreamDeleter::operator() (
103 FileStream* file_stream) const {
104 if (file_stream) {
105 base::WorkerPool::PostTask(FROM_HERE,
106 base::Bind(&base::DeletePointer<FileStream>,
107 file_stream),
108 true /* task_is_slow */);
112 UploadFileElementReader::UploadFileElementReader(
113 const FilePath& path,
114 uint64 range_offset,
115 uint64 range_length,
116 const base::Time& expected_modification_time)
117 : path_(path),
118 range_offset_(range_offset),
119 range_length_(range_length),
120 expected_modification_time_(expected_modification_time),
121 content_length_(0),
122 bytes_remaining_(0),
123 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
126 UploadFileElementReader::~UploadFileElementReader() {
129 int UploadFileElementReader::Init(const CompletionCallback& callback) {
130 Reset();
132 ScopedFileStreamPtr* file_stream = new ScopedFileStreamPtr;
133 uint64* content_length = new uint64;
134 const bool posted = base::PostTaskAndReplyWithResult(
135 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
136 FROM_HERE,
137 base::Bind(&InitInternal,
138 path_,
139 range_offset_,
140 range_length_,
141 expected_modification_time_,
142 file_stream,
143 content_length),
144 base::Bind(&UploadFileElementReader::OnInitCompleted,
145 weak_ptr_factory_.GetWeakPtr(),
146 base::Owned(file_stream),
147 base::Owned(content_length),
148 callback));
149 DCHECK(posted);
150 return ERR_IO_PENDING;
153 int UploadFileElementReader::InitSync() {
154 Reset();
156 ScopedFileStreamPtr file_stream;
157 uint64 content_length = 0;
158 const int result = InitInternal(path_, range_offset_, range_length_,
159 expected_modification_time_,
160 &file_stream, &content_length);
161 OnInitCompleted(&file_stream, &content_length, CompletionCallback(), result);
162 return result;
165 uint64 UploadFileElementReader::GetContentLength() const {
166 if (overriding_content_length)
167 return overriding_content_length;
168 return content_length_;
171 uint64 UploadFileElementReader::BytesRemaining() const {
172 return bytes_remaining_;
175 int UploadFileElementReader::Read(IOBuffer* buf,
176 int buf_length,
177 const CompletionCallback& callback) {
178 DCHECK(!callback.is_null());
180 if (BytesRemaining() == 0)
181 return 0;
183 // Save the value of file_stream_.get() before base::Passed() invalidates it.
184 FileStream* file_stream_ptr = file_stream_.get();
185 // Pass the ownership of file_stream_ to the worker pool to safely perform
186 // operation even when |this| is destructed before the read completes.
187 const bool posted = base::PostTaskAndReplyWithResult(
188 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
189 FROM_HERE,
190 base::Bind(&ReadInternal,
191 scoped_refptr<IOBuffer>(buf),
192 buf_length,
193 BytesRemaining(),
194 file_stream_ptr),
195 base::Bind(&UploadFileElementReader::OnReadCompleted,
196 weak_ptr_factory_.GetWeakPtr(),
197 base::Passed(&file_stream_),
198 callback));
199 DCHECK(posted);
200 return ERR_IO_PENDING;
203 int UploadFileElementReader::ReadSync(IOBuffer* buf, int buf_length) {
204 const int result = ReadInternal(buf, buf_length, BytesRemaining(),
205 file_stream_.get());
206 OnReadCompleted(file_stream_.Pass(), CompletionCallback(), result);
207 return result;
210 void UploadFileElementReader::Reset() {
211 weak_ptr_factory_.InvalidateWeakPtrs();
212 bytes_remaining_ = 0;
213 content_length_ = 0;
214 file_stream_.reset();
217 void UploadFileElementReader::OnInitCompleted(
218 ScopedFileStreamPtr* file_stream,
219 uint64* content_length,
220 const CompletionCallback& callback,
221 int result) {
222 file_stream_.swap(*file_stream);
223 content_length_ = *content_length;
224 bytes_remaining_ = GetContentLength();
225 if (!callback.is_null())
226 callback.Run(result);
229 void UploadFileElementReader::OnReadCompleted(
230 ScopedFileStreamPtr file_stream,
231 const CompletionCallback& callback,
232 int result) {
233 file_stream_.swap(file_stream);
234 DCHECK_GE(static_cast<int>(bytes_remaining_), result);
235 bytes_remaining_ -= result;
236 if (!callback.is_null())
237 callback.Run(result);
240 UploadFileElementReader::ScopedOverridingContentLengthForTests::
241 ScopedOverridingContentLengthForTests(uint64 value) {
242 overriding_content_length = value;
245 UploadFileElementReader::ScopedOverridingContentLengthForTests::
246 ~ScopedOverridingContentLengthForTests() {
247 overriding_content_length = 0;
250 } // namespace net