OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/upload_file_element_reader.h" | 5 #include "net/base/upload_content_url_element_reader_android.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/task_runner_util.h" | 10 #include "base/task_runner_util.h" |
11 #include "net/android/content_uri_utils.h" | |
11 #include "net/base/file_stream.h" | 12 #include "net/base/file_stream.h" |
12 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
13 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
14 | 15 |
15 namespace net { | 16 namespace net { |
16 | 17 |
17 namespace { | 18 namespace { |
18 | 19 |
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; | |
22 | |
23 // This function is used to implement Init(). | 20 // This function is used to implement Init(). |
joth
2013/10/29 01:30:25
the duplication with UploadFileElementReader does
qinmin
2013/10/29 02:45:57
ok, will do.
On 2013/10/29 01:30:25, joth wrote:
| |
24 template<typename FileStreamDeleter> | 21 template<typename FileStreamDeleter> |
25 int InitInternal(const base::FilePath& path, | 22 int InitInternal(const GURL& content_url, |
26 uint64 range_offset, | 23 uint64 range_offset, |
27 uint64 range_length, | 24 uint64 range_length, |
28 const base::Time& expected_modification_time, | 25 const base::Time& expected_modification_time, |
29 scoped_ptr<FileStream, FileStreamDeleter>* out_file_stream, | 26 scoped_ptr<FileStream, FileStreamDeleter>* out_file_stream, |
30 uint64* out_content_length) { | 27 uint64* out_content_length) { |
31 scoped_ptr<FileStream> file_stream(new FileStream(NULL)); | 28 scoped_ptr<FileStream> file_stream(new FileStream(NULL)); |
32 int64 rv = file_stream->OpenSync( | 29 int64 rv = file_stream->OpenContentUrlSync( |
33 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); | 30 content_url, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); |
34 if (rv != OK) { | 31 if (rv != OK) { |
35 // If the file can't be opened, we'll just upload an empty file. | 32 // If the file can't be opened, we'll just upload an empty file. |
36 DLOG(WARNING) << "Failed to open \"" << path.value() | 33 DLOG(WARNING) << "Failed to open \"" << content_url.spec() |
37 << "\" for reading: " << rv; | 34 << "\" for reading: " << rv; |
38 file_stream.reset(); | 35 file_stream.reset(); |
39 } else if (range_offset) { | 36 } else if (range_offset) { |
40 rv = file_stream->SeekSync(FROM_BEGIN, range_offset); | 37 rv = file_stream->SeekSync(FROM_BEGIN, range_offset); |
41 if (rv < 0) { | 38 if (rv < 0) { |
42 DLOG(WARNING) << "Failed to seek \"" << path.value() | 39 DLOG(WARNING) << "Failed to seek \"" << content_url.spec() |
43 << "\" to offset: " << range_offset << " (" << rv << ")"; | 40 << "\" to offset: " << range_offset << " (" << rv << ")"; |
44 file_stream.reset(); | 41 file_stream.reset(); |
45 } | 42 } |
46 } | 43 } |
47 | 44 |
48 int64 length = 0; | 45 int64 length = GetContentUrlLengthSync(content_url); |
49 if (file_stream.get() && | 46 if (file_stream.get() && length >= 0 && |
50 file_util::GetFileSize(path, &length) && | |
51 range_offset < static_cast<uint64>(length)) { | 47 range_offset < static_cast<uint64>(length)) { |
52 // Compensate for the offset. | 48 // Compensate for the offset. |
53 length = std::min(length - range_offset, range_length); | 49 length = std::min(length - range_offset, range_length); |
50 } else { | |
51 length = 0; | |
54 } | 52 } |
55 *out_content_length = length; | 53 *out_content_length = length; |
56 out_file_stream->reset(file_stream.release()); | 54 out_file_stream->reset(file_stream.release()); |
57 | 55 |
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; | |
67 } | |
68 } | |
69 | |
70 return OK; | 56 return OK; |
71 } | 57 } |
72 | 58 |
73 // This function is used to implement Read(). | 59 // This function is used to implement Read(). |
74 int ReadInternal(scoped_refptr<IOBuffer> buf, | 60 int ReadInternal(scoped_refptr<IOBuffer> buf, |
75 int buf_length, | 61 int buf_length, |
76 uint64 bytes_remaining, | 62 uint64 bytes_remaining, |
77 FileStream* file_stream) { | 63 FileStream* file_stream) { |
78 DCHECK_LT(0, buf_length); | 64 DCHECK_LT(0, buf_length); |
79 | 65 |
80 const uint64 num_bytes_to_read = | 66 const uint64 num_bytes_to_read = |
81 std::min(bytes_remaining, static_cast<uint64>(buf_length)); | 67 std::min(bytes_remaining, static_cast<uint64>(buf_length)); |
82 | 68 |
83 int result = 0; | 69 int result = 0; |
84 if (num_bytes_to_read > 0) { | 70 if (num_bytes_to_read > 0) { |
85 DCHECK(file_stream); // file_stream is non-null if content_length_ > 0. | 71 DCHECK(file_stream); // file_stream is non-null if content_length_ > 0. |
86 result = file_stream->ReadSync(buf->data(), num_bytes_to_read); | 72 result = file_stream->ReadSync(buf->data(), num_bytes_to_read); |
87 if (result == 0) // Reached end-of-file earlier than expected. | 73 if (result == 0) // Reached end-of-file earlier than expected. |
88 result = ERR_UPLOAD_FILE_CHANGED; | 74 result = ERR_UPLOAD_FILE_CHANGED; |
89 } | 75 } |
90 return result; | 76 return result; |
91 } | 77 } |
92 | 78 |
93 } // namespace | 79 } // namespace |
94 | 80 |
95 UploadFileElementReader::FileStreamDeleter::FileStreamDeleter( | 81 UploadContentUrlElementReader::FileStreamDeleter::FileStreamDeleter( |
96 base::TaskRunner* task_runner) : task_runner_(task_runner) { | 82 base::TaskRunner* task_runner) : task_runner_(task_runner) { |
97 DCHECK(task_runner_.get()); | 83 DCHECK(task_runner_.get()); |
98 } | 84 } |
99 | 85 |
100 UploadFileElementReader::FileStreamDeleter::~FileStreamDeleter() {} | 86 UploadContentUrlElementReader::FileStreamDeleter::~FileStreamDeleter() {} |
101 | 87 |
102 void UploadFileElementReader::FileStreamDeleter::operator() ( | 88 void UploadContentUrlElementReader::FileStreamDeleter::operator() ( |
103 FileStream* file_stream) const { | 89 FileStream* file_stream) const { |
104 if (file_stream) { | 90 if (file_stream) { |
105 task_runner_->PostTask(FROM_HERE, | 91 task_runner_->PostTask(FROM_HERE, |
106 base::Bind(&base::DeletePointer<FileStream>, | 92 base::Bind(&base::DeletePointer<FileStream>, |
107 file_stream)); | 93 file_stream)); |
108 } | 94 } |
109 } | 95 } |
110 | 96 |
111 UploadFileElementReader::UploadFileElementReader( | 97 UploadContentUrlElementReader::UploadContentUrlElementReader( |
112 base::TaskRunner* task_runner, | 98 base::TaskRunner* task_runner, |
113 const base::FilePath& path, | 99 const GURL& content_url, |
114 uint64 range_offset, | 100 uint64 range_offset, |
115 uint64 range_length, | 101 uint64 range_length, |
116 const base::Time& expected_modification_time) | 102 const base::Time& expected_modification_time) |
117 : task_runner_(task_runner), | 103 : task_runner_(task_runner), |
118 path_(path), | 104 content_url_(content_url), |
119 range_offset_(range_offset), | 105 range_offset_(range_offset), |
120 range_length_(range_length), | 106 range_length_(range_length), |
121 expected_modification_time_(expected_modification_time), | 107 expected_modification_time_(expected_modification_time), |
122 file_stream_(NULL, FileStreamDeleter(task_runner_.get())), | 108 file_stream_(NULL, FileStreamDeleter(task_runner_.get())), |
123 content_length_(0), | 109 content_length_(0), |
124 bytes_remaining_(0), | 110 bytes_remaining_(0), |
125 weak_ptr_factory_(this) { | 111 weak_ptr_factory_(this) { |
126 DCHECK(task_runner_.get()); | 112 DCHECK(task_runner_.get()); |
127 } | 113 } |
128 | 114 |
129 UploadFileElementReader::~UploadFileElementReader() { | 115 UploadContentUrlElementReader::~UploadContentUrlElementReader() {} |
130 } | |
131 | 116 |
132 const UploadFileElementReader* UploadFileElementReader::AsFileReader() const { | 117 int UploadContentUrlElementReader::Init(const CompletionCallback& callback) { |
133 return this; | |
134 } | |
135 | |
136 int UploadFileElementReader::Init(const CompletionCallback& callback) { | |
137 DCHECK(!callback.is_null()); | 118 DCHECK(!callback.is_null()); |
138 Reset(); | 119 Reset(); |
139 | |
140 ScopedFileStreamPtr* file_stream = | 120 ScopedFileStreamPtr* file_stream = |
141 new ScopedFileStreamPtr(NULL, FileStreamDeleter(task_runner_.get())); | 121 new ScopedFileStreamPtr(NULL, FileStreamDeleter(task_runner_.get())); |
142 uint64* content_length = new uint64; | 122 uint64* content_length = new uint64; |
143 const bool posted = base::PostTaskAndReplyWithResult( | 123 const bool posted = base::PostTaskAndReplyWithResult( |
144 task_runner_.get(), | 124 task_runner_.get(), |
145 FROM_HERE, | 125 FROM_HERE, |
146 base::Bind(&InitInternal<FileStreamDeleter>, | 126 base::Bind(&InitInternal<FileStreamDeleter>, |
147 path_, | 127 content_url_, |
148 range_offset_, | 128 range_offset_, |
149 range_length_, | 129 range_length_, |
150 expected_modification_time_, | 130 expected_modification_time_, |
151 file_stream, | 131 file_stream, |
152 content_length), | 132 content_length), |
153 base::Bind(&UploadFileElementReader::OnInitCompleted, | 133 base::Bind(&UploadContentUrlElementReader::OnInitCompleted, |
154 weak_ptr_factory_.GetWeakPtr(), | 134 weak_ptr_factory_.GetWeakPtr(), |
155 base::Owned(file_stream), | 135 base::Owned(file_stream), |
156 base::Owned(content_length), | 136 base::Owned(content_length), |
157 callback)); | 137 callback)); |
158 DCHECK(posted); | 138 DCHECK(posted); |
159 return ERR_IO_PENDING; | 139 return ERR_IO_PENDING; |
160 } | 140 } |
161 | 141 |
162 uint64 UploadFileElementReader::GetContentLength() const { | 142 uint64 UploadContentUrlElementReader::GetContentLength() const { |
163 if (overriding_content_length) | |
164 return overriding_content_length; | |
165 return content_length_; | 143 return content_length_; |
166 } | 144 } |
167 | 145 |
168 uint64 UploadFileElementReader::BytesRemaining() const { | 146 uint64 UploadContentUrlElementReader::BytesRemaining() const { |
169 return bytes_remaining_; | 147 return bytes_remaining_; |
170 } | 148 } |
171 | 149 |
172 int UploadFileElementReader::Read(IOBuffer* buf, | 150 int UploadContentUrlElementReader::Read(IOBuffer* buf, |
173 int buf_length, | 151 int buf_length, |
174 const CompletionCallback& callback) { | 152 const CompletionCallback& callback) { |
175 DCHECK(!callback.is_null()); | 153 DCHECK(!callback.is_null()); |
176 | 154 |
177 if (BytesRemaining() == 0) | 155 if (BytesRemaining() == 0) |
178 return 0; | 156 return 0; |
179 | 157 |
180 // Save the value of file_stream_.get() before base::Passed() invalidates it. | 158 // Save the value of file_stream_.get() before base::Passed() invalidates it. |
181 FileStream* file_stream_ptr = file_stream_.get(); | 159 FileStream* file_stream_ptr = file_stream_.get(); |
182 // Pass the ownership of file_stream_ to the worker pool to safely perform | 160 // Pass the ownership of file_stream_ to the worker pool to safely perform |
183 // operation even when |this| is destructed before the read completes. | 161 // operation even when |this| is destructed before the read completes. |
184 const bool posted = base::PostTaskAndReplyWithResult( | 162 const bool posted = base::PostTaskAndReplyWithResult( |
185 task_runner_.get(), | 163 task_runner_.get(), |
186 FROM_HERE, | 164 FROM_HERE, |
187 base::Bind(&ReadInternal, | 165 base::Bind(&ReadInternal, |
188 scoped_refptr<IOBuffer>(buf), | 166 scoped_refptr<IOBuffer>(buf), |
189 buf_length, | 167 buf_length, |
190 BytesRemaining(), | 168 BytesRemaining(), |
191 file_stream_ptr), | 169 file_stream_ptr), |
192 base::Bind(&UploadFileElementReader::OnReadCompleted, | 170 base::Bind(&UploadContentUrlElementReader::OnReadCompleted, |
193 weak_ptr_factory_.GetWeakPtr(), | 171 weak_ptr_factory_.GetWeakPtr(), |
194 base::Passed(&file_stream_), | 172 base::Passed(&file_stream_), |
195 callback)); | 173 callback)); |
196 DCHECK(posted); | 174 DCHECK(posted); |
197 return ERR_IO_PENDING; | 175 return ERR_IO_PENDING; |
198 } | 176 } |
199 | 177 |
200 void UploadFileElementReader::Reset() { | 178 void UploadContentUrlElementReader::Reset() { |
201 weak_ptr_factory_.InvalidateWeakPtrs(); | 179 weak_ptr_factory_.InvalidateWeakPtrs(); |
202 bytes_remaining_ = 0; | 180 bytes_remaining_ = 0; |
203 content_length_ = 0; | 181 content_length_ = 0; |
204 file_stream_.reset(); | 182 file_stream_.reset(); |
205 } | 183 } |
206 | 184 |
207 void UploadFileElementReader::OnInitCompleted( | 185 void UploadContentUrlElementReader::OnInitCompleted( |
208 ScopedFileStreamPtr* file_stream, | 186 ScopedFileStreamPtr* file_stream, |
209 uint64* content_length, | 187 uint64* content_length, |
210 const CompletionCallback& callback, | 188 const CompletionCallback& callback, |
211 int result) { | 189 int result) { |
212 file_stream_.swap(*file_stream); | 190 file_stream_.swap(*file_stream); |
213 content_length_ = *content_length; | 191 content_length_ = *content_length; |
214 bytes_remaining_ = GetContentLength(); | 192 bytes_remaining_ = GetContentLength(); |
215 if (!callback.is_null()) | 193 if (!callback.is_null()) |
216 callback.Run(result); | 194 callback.Run(result); |
217 } | 195 } |
218 | 196 |
219 void UploadFileElementReader::OnReadCompleted( | 197 void UploadContentUrlElementReader::OnReadCompleted( |
220 ScopedFileStreamPtr file_stream, | 198 ScopedFileStreamPtr file_stream, |
221 const CompletionCallback& callback, | 199 const CompletionCallback& callback, |
222 int result) { | 200 int result) { |
223 file_stream_.swap(file_stream); | 201 file_stream_.swap(file_stream); |
224 if (result > 0) { | 202 if (result > 0) { |
225 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result)); | 203 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result)); |
226 bytes_remaining_ -= result; | 204 bytes_remaining_ -= result; |
227 } | 205 } |
228 if (!callback.is_null()) | 206 if (!callback.is_null()) |
229 callback.Run(result); | 207 callback.Run(result); |
230 } | 208 } |
231 | 209 |
232 UploadFileElementReader::ScopedOverridingContentLengthForTests:: | |
233 ScopedOverridingContentLengthForTests(uint64 value) { | |
234 overriding_content_length = value; | |
235 } | |
236 | |
237 UploadFileElementReader::ScopedOverridingContentLengthForTests:: | |
238 ~ScopedOverridingContentLengthForTests() { | |
239 overriding_content_length = 0; | |
240 } | |
241 | |
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) { | |
253 } | |
254 | |
255 UploadFileElementReaderSync::~UploadFileElementReaderSync() { | |
256 } | |
257 | |
258 int UploadFileElementReaderSync::Init(const CompletionCallback& callback) { | |
259 bytes_remaining_ = 0; | |
260 content_length_ = 0; | |
261 file_stream_.reset(); | |
262 | |
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; | |
268 } | |
269 | |
270 uint64 UploadFileElementReaderSync::GetContentLength() const { | |
271 return content_length_; | |
272 } | |
273 | |
274 uint64 UploadFileElementReaderSync::BytesRemaining() const { | |
275 return bytes_remaining_; | |
276 } | |
277 | |
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; | |
286 } | |
287 return result; | |
288 } | |
289 | |
290 } // namespace net | 210 } // namespace net |
OLD | NEW |