Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/download/download_file_impl.h" | 5 #include "content/browser/download/download_file_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 source_stream)); | 367 source_stream)); |
| 368 } | 368 } |
| 369 | 369 |
| 370 if (total_incoming_data_size) | 370 if (total_incoming_data_size) |
| 371 RecordFileThreadReceiveBuffers(num_buffers); | 371 RecordFileThreadReceiveBuffers(num_buffers); |
| 372 | 372 |
| 373 RecordContiguousWriteTime(now - start); | 373 RecordContiguousWriteTime(now - start); |
| 374 | 374 |
| 375 // Take care of communication with our observer. | 375 // Take care of communication with our observer. |
| 376 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 376 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 377 // Error case for both upstream source and file write. | 377 HandleStreamError(source_stream, reason); |
| 378 // Shut down processing and signal an error to our observer. | |
| 379 // Our observer will clean us up. | |
| 380 source_stream->stream_reader()->RegisterCallback(base::Closure()); | |
| 381 weak_factory_.InvalidateWeakPtrs(); | |
| 382 SendUpdate(); // Make info up to date before error. | |
| 383 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | |
| 384 BrowserThread::PostTask( | |
| 385 BrowserThread::UI, FROM_HERE, | |
| 386 base::Bind(&DownloadDestinationObserver::DestinationError, observer_, | |
| 387 reason, TotalBytesReceived(), base::Passed(&hash_state))); | |
| 388 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { | 378 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { |
| 389 // Signal successful completion or termination of the current stream. | 379 // Signal successful completion or termination of the current stream. |
| 390 source_stream->stream_reader()->RegisterCallback(base::Closure()); | 380 source_stream->stream_reader()->RegisterCallback(base::Closure()); |
| 391 source_stream->set_finished(true); | 381 source_stream->set_finished(true); |
| 392 | 382 |
| 393 // Inform observers. | 383 // Inform observers. |
| 394 SendUpdate(); | 384 SendUpdate(); |
| 395 | 385 |
| 396 // All the stream reader are completed, shut down file IO processing. | 386 // All the stream reader are completed, shut down file IO processing. |
| 397 if (IsDownloadCompleted()) { | 387 if (IsDownloadCompleted()) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 return false; | 498 return false; |
| 509 } | 499 } |
| 510 DCHECK_EQ(slices_to_download[0].offset, | 500 DCHECK_EQ(slices_to_download[0].offset, |
| 511 stream_for_last_slice->offset() + | 501 stream_for_last_slice->offset() + |
| 512 stream_for_last_slice->bytes_written()); | 502 stream_for_last_slice->bytes_written()); |
| 513 } | 503 } |
| 514 | 504 |
| 515 return true; | 505 return true; |
| 516 } | 506 } |
| 517 | 507 |
| 508 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, | |
| 509 DownloadInterruptReason reason) { | |
| 510 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 511 source_stream->stream_reader()->RegisterCallback(base::Closure()); | |
| 512 source_stream->set_finished(true); | |
| 513 | |
| 514 bool can_recover_from_error = false; | |
| 515 | |
| 516 if (is_sparse_file_) { | |
| 517 auto initial_source_stream = source_streams_.find(save_info_->offset); | |
|
xingliu
2017/03/18 22:27:34
What if the error is triggered by the initial stre
qinmin
2017/03/20 20:59:21
If the error is trigger by initial stream, set_fin
xingliu
2017/03/20 22:33:33
I see.
David Trainor- moved to gerrit
2017/03/21 17:00:16
Should we just call this stream_iterator or someth
qinmin
2017/03/21 19:29:17
Done.
| |
| 518 DCHECK(initial_source_stream != source_streams_.end()); | |
| 519 SourceStream* initial_stream = initial_source_stream->second.get(); | |
| 520 // If the initial request is alive, check if it can help download all the | |
|
David Trainor- moved to gerrit
2017/03/21 17:00:16
Can we add a TODO to figure out allowing adjacent
qinmin
2017/03/21 19:29:17
Done.
| |
| 521 // data left by this source stream. We want to avoid the situation that | |
| 522 // a server always fail additional requests from the client thus causing the | |
| 523 // initial request and the download going nowhere. | |
| 524 if (!initial_stream->is_finished() && | |
| 525 (initial_stream->length() == DownloadSaveInfo::kLengthFullContent || | |
| 526 initial_stream->offset() + initial_stream->length() > | |
| 527 source_stream->offset() + source_stream->length())) { | |
| 528 // The initial stream will download all data downloading from its offset | |
|
xingliu
2017/03/18 22:27:34
If there is a new slice added, does the initial sl
qinmin
2017/03/20 20:59:21
No. For example, there are stream A, B, C ordered
xingliu
2017/03/20 22:33:33
sgtm.
David Trainor- moved to gerrit
2017/03/21 17:00:16
Hmm that seems like it might be a really common oc
qinmin
2017/03/21 19:29:17
This will add more complexity to the current logic
David Trainor- moved to gerrit
2017/03/22 03:10:55
Okay I guess it's fine to postpone this for now.
| |
| 529 // to source_stream->offset(). Close all other streams in the middle. | |
| 530 for (auto& stream : source_streams_) { | |
| 531 if (stream.second->offset() < source_stream->offset() && | |
| 532 stream.second.get() != initial_stream) { | |
| 533 DCHECK_EQ(stream.second->bytes_written(), 0); | |
|
xingliu
2017/03/18 22:27:34
Is it safe to assume streams in the middle never w
qinmin
2017/03/20 20:59:21
Yes, if a stream in the middle writes something, i
xingliu
2017/03/20 22:33:33
I see.
David Trainor- moved to gerrit
2017/03/21 17:00:16
Who kills the outstanding request if the middle st
xingliu
2017/03/21 17:48:04
DownloadFileImpl and all objects under it will get
David Trainor- moved to gerrit
2017/03/22 03:10:55
Thanks!
| |
| 534 stream.second->stream_reader()->RegisterCallback(base::Closure()); | |
| 535 stream.second->set_finished(true); | |
| 536 } | |
| 537 } | |
| 538 can_recover_from_error = true; | |
| 539 } | |
| 540 } | |
| 541 | |
| 542 SendUpdate(); // Make info up to date before error. | |
| 543 | |
| 544 if (!can_recover_from_error) { | |
| 545 // Error case for both upstream source and file write. | |
| 546 // Shut down processing and signal an error to our observer. | |
| 547 // Our observer will clean us up. | |
| 548 weak_factory_.InvalidateWeakPtrs(); | |
|
David Trainor- moved to gerrit
2017/03/21 17:00:16
Should we pull out the shutdown code to a common h
qinmin
2017/03/21 19:29:17
No, we don't have the lines duplicated. It is simi
David Trainor- moved to gerrit
2017/03/22 03:10:55
Yeah makes sense. Thanks
| |
| 549 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | |
| 550 BrowserThread::PostTask( | |
| 551 BrowserThread::UI, FROM_HERE, | |
| 552 base::Bind(&DownloadDestinationObserver::DestinationError, observer_, | |
| 553 reason, TotalBytesReceived(), base::Passed(&hash_state))); | |
|
xingliu
2017/03/20 22:33:33
nit%: Not in this CL, since we allow duplicate IO
xingliu
2017/03/20 22:35:10
make sure it's ok for user to see larger bytes num
qinmin
2017/03/21 19:29:17
This won't happen. TotalBytesReceived is calculate
| |
| 554 } | |
| 555 } | |
| 556 | |
| 518 DownloadFileImpl::RenameParameters::RenameParameters( | 557 DownloadFileImpl::RenameParameters::RenameParameters( |
| 519 RenameOption option, | 558 RenameOption option, |
| 520 const base::FilePath& new_path, | 559 const base::FilePath& new_path, |
| 521 const RenameCompletionCallback& completion_callback) | 560 const RenameCompletionCallback& completion_callback) |
| 522 : option(option), | 561 : option(option), |
| 523 new_path(new_path), | 562 new_path(new_path), |
| 524 retries_left(kMaxRenameRetries), | 563 retries_left(kMaxRenameRetries), |
| 525 completion_callback(completion_callback) {} | 564 completion_callback(completion_callback) {} |
| 526 | 565 |
| 527 DownloadFileImpl::RenameParameters::~RenameParameters() {} | 566 DownloadFileImpl::RenameParameters::~RenameParameters() {} |
| 528 | 567 |
| 529 } // namespace content | 568 } // namespace content |
| OLD | NEW |