Chromium Code Reviews| 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 |