OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "chrome/browser/chromeos/drive/drive_file_stream_reader.h" | 5 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 | 9 |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } else { | 145 } else { |
146 // An error occurs. Close the |file_reader_|. | 146 // An error occurs. Close the |file_reader_|. |
147 file_reader_.reset(); | 147 file_reader_.reset(); |
148 } | 148 } |
149 callback.Run(read_result); | 149 callback.Run(read_result); |
150 } | 150 } |
151 | 151 |
152 NetworkReaderProxy::NetworkReaderProxy( | 152 NetworkReaderProxy::NetworkReaderProxy( |
153 int64 offset, | 153 int64 offset, |
154 int64 content_length, | 154 int64 content_length, |
| 155 int64 full_content_length, |
155 const base::Closure& job_canceller) | 156 const base::Closure& job_canceller) |
156 : remaining_offset_(offset), | 157 : remaining_offset_(offset), |
157 remaining_content_length_(content_length), | 158 remaining_content_length_(content_length), |
| 159 is_full_download_(offset + content_length == full_content_length), |
158 error_code_(net::OK), | 160 error_code_(net::OK), |
159 buffer_length_(0), | 161 buffer_length_(0), |
160 job_canceller_(job_canceller) { | 162 job_canceller_(job_canceller) { |
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
162 } | 164 } |
163 | 165 |
164 NetworkReaderProxy::~NetworkReaderProxy() { | 166 NetworkReaderProxy::~NetworkReaderProxy() { |
165 if (!job_canceller_.is_null()) { | 167 if (!job_canceller_.is_null()) { |
166 job_canceller_.Run(); | 168 job_canceller_.Run(); |
167 } | 169 } |
(...skipping 30 matching lines...) Expand all Loading... |
198 // No data is available. Keep the arguments, and return pending status. | 200 // No data is available. Keep the arguments, and return pending status. |
199 buffer_ = buffer; | 201 buffer_ = buffer; |
200 buffer_length_ = buffer_length; | 202 buffer_length_ = buffer_length; |
201 callback_ = callback; | 203 callback_ = callback; |
202 return net::ERR_IO_PENDING; | 204 return net::ERR_IO_PENDING; |
203 } | 205 } |
204 | 206 |
205 int result = ReadInternal(&pending_data_, buffer, buffer_length); | 207 int result = ReadInternal(&pending_data_, buffer, buffer_length); |
206 remaining_content_length_ -= result; | 208 remaining_content_length_ -= result; |
207 DCHECK_GE(remaining_content_length_, 0); | 209 DCHECK_GE(remaining_content_length_, 0); |
| 210 |
| 211 // Although OnCompleted() should reset |job_canceller_| when download is done, |
| 212 // due to timing issues the ReaderProxy instance may be destructed before the |
| 213 // notification. To fix the case we reset here earlier. |
| 214 if (is_full_download_ && remaining_content_length_ == 0) |
| 215 job_canceller_.Reset(); |
| 216 |
208 return result; | 217 return result; |
209 } | 218 } |
210 | 219 |
211 void NetworkReaderProxy::OnGetContent(scoped_ptr<std::string> data) { | 220 void NetworkReaderProxy::OnGetContent(scoped_ptr<std::string> data) { |
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
213 DCHECK(data && !data->empty()); | 222 DCHECK(data && !data->empty()); |
214 | 223 |
215 if (remaining_offset_ >= static_cast<int64>(data->length())) { | 224 if (remaining_offset_ >= static_cast<int64>(data->length())) { |
216 // Skip unneeded leading data. | 225 // Skip unneeded leading data. |
217 remaining_offset_ -= data->length(); | 226 remaining_offset_ -= data->length(); |
218 return; | 227 return; |
219 } | 228 } |
220 | 229 |
221 if (remaining_offset_ > 0) { | 230 if (remaining_offset_ > 0) { |
222 // Erase unnecessary leading bytes. | 231 // Erase unnecessary leading bytes. |
223 data->erase(0, static_cast<size_t>(remaining_offset_)); | 232 data->erase(0, static_cast<size_t>(remaining_offset_)); |
224 remaining_offset_ = 0; | 233 remaining_offset_ = 0; |
225 } | 234 } |
226 | 235 |
227 pending_data_.push_back(data.release()); | 236 pending_data_.push_back(data.release()); |
228 if (!buffer_.get()) { | 237 if (!buffer_.get()) { |
229 // No pending Read operation. | 238 // No pending Read operation. |
230 return; | 239 return; |
231 } | 240 } |
232 | 241 |
233 int result = ReadInternal(&pending_data_, buffer_.get(), buffer_length_); | 242 int result = ReadInternal(&pending_data_, buffer_.get(), buffer_length_); |
234 remaining_content_length_ -= result; | 243 remaining_content_length_ -= result; |
235 DCHECK_GE(remaining_content_length_, 0); | 244 DCHECK_GE(remaining_content_length_, 0); |
236 | 245 |
| 246 if (is_full_download_ && remaining_content_length_ == 0) |
| 247 job_canceller_.Reset(); |
| 248 |
237 buffer_ = NULL; | 249 buffer_ = NULL; |
238 buffer_length_ = 0; | 250 buffer_length_ = 0; |
239 DCHECK(!callback_.is_null()); | 251 DCHECK(!callback_.is_null()); |
240 base::ResetAndReturn(&callback_).Run(result); | 252 base::ResetAndReturn(&callback_).Run(result); |
241 } | 253 } |
242 | 254 |
243 void NetworkReaderProxy::OnCompleted(FileError error) { | 255 void NetworkReaderProxy::OnCompleted(FileError error) { |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
245 // The downloading is completed, so we do not need to cancel the job | 257 // The downloading is completed, so we do not need to cancel the job |
246 // in the destructor. | 258 // in the destructor. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 weak_ptr_factory_.InvalidateWeakPtrs(); | 410 weak_ptr_factory_.InvalidateWeakPtrs(); |
399 callback.Run( | 411 callback.Run( |
400 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); | 412 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>()); |
401 return; | 413 return; |
402 } | 414 } |
403 | 415 |
404 if (local_cache_file_path.empty()) { | 416 if (local_cache_file_path.empty()) { |
405 // The file is not cached, and being downloaded. | 417 // The file is not cached, and being downloaded. |
406 reader_proxy_.reset( | 418 reader_proxy_.reset( |
407 new internal::NetworkReaderProxy( | 419 new internal::NetworkReaderProxy( |
408 range_start, range_length, cancel_download_closure_)); | 420 range_start, range_length, |
| 421 entry->file_info().size(), cancel_download_closure_)); |
409 callback.Run(net::OK, entry.Pass()); | 422 callback.Run(net::OK, entry.Pass()); |
410 return; | 423 return; |
411 } | 424 } |
412 | 425 |
413 // Otherwise, open the stream for file. | 426 // Otherwise, open the stream for file. |
414 scoped_ptr<util::LocalFileReader> file_reader( | 427 scoped_ptr<util::LocalFileReader> file_reader( |
415 new util::LocalFileReader(file_task_runner_.get())); | 428 new util::LocalFileReader(file_task_runner_.get())); |
416 util::LocalFileReader* file_reader_ptr = file_reader.get(); | 429 util::LocalFileReader* file_reader_ptr = file_reader.get(); |
417 file_reader_ptr->Open( | 430 file_reader_ptr->Open( |
418 local_cache_file_path, | 431 local_cache_file_path, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 // Note: due to the same reason, LocalReaderProxy::OnCompleted may | 482 // Note: due to the same reason, LocalReaderProxy::OnCompleted may |
470 // or may not be called. This is timing issue, and it is difficult to avoid | 483 // or may not be called. This is timing issue, and it is difficult to avoid |
471 // unfortunately. | 484 // unfortunately. |
472 if (error != FILE_ERROR_OK) { | 485 if (error != FILE_ERROR_OK) { |
473 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); | 486 callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>()); |
474 } | 487 } |
475 } | 488 } |
476 } | 489 } |
477 | 490 |
478 } // namespace drive | 491 } // namespace drive |
OLD | NEW |