Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: content/browser/download/download_file_impl.cc

Issue 2748103014: Allow the initial request to take over failed parallel requests. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/download/download_file_impl.cc
diff --git a/content/browser/download/download_file_impl.cc b/content/browser/download/download_file_impl.cc
index eb1ef9bfd59e107735c6b49daf8f34df324f1191..4c06e52ee304bdb96a11aa9369a9a9a7de635a9e 100644
--- a/content/browser/download/download_file_impl.cc
+++ b/content/browser/download/download_file_impl.cc
@@ -374,17 +374,7 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
// Take care of communication with our observer.
if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
- // Error case for both upstream source and file write.
- // Shut down processing and signal an error to our observer.
- // Our observer will clean us up.
- source_stream->stream_reader()->RegisterCallback(base::Closure());
- weak_factory_.InvalidateWeakPtrs();
- SendUpdate(); // Make info up to date before error.
- std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
- reason, TotalBytesReceived(), base::Passed(&hash_state)));
+ HandleStreamError(source_stream, reason);
} else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) {
// Signal successful completion or termination of the current stream.
source_stream->stream_reader()->RegisterCallback(base::Closure());
@@ -515,6 +505,55 @@ bool DownloadFileImpl::IsDownloadCompleted() {
return true;
}
+void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
+ DownloadInterruptReason reason) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ source_stream->stream_reader()->RegisterCallback(base::Closure());
+ source_stream->set_finished(true);
+
+ bool can_recover_from_error = false;
+
+ if (is_sparse_file_) {
+ 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.
+ DCHECK(initial_source_stream != source_streams_.end());
+ SourceStream* initial_stream = initial_source_stream->second.get();
+ // 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.
+ // data left by this source stream. We want to avoid the situation that
+ // a server always fail additional requests from the client thus causing the
+ // initial request and the download going nowhere.
+ if (!initial_stream->is_finished() &&
+ (initial_stream->length() == DownloadSaveInfo::kLengthFullContent ||
+ initial_stream->offset() + initial_stream->length() >
+ source_stream->offset() + source_stream->length())) {
+ // 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.
+ // to source_stream->offset(). Close all other streams in the middle.
+ for (auto& stream : source_streams_) {
+ if (stream.second->offset() < source_stream->offset() &&
+ stream.second.get() != initial_stream) {
+ 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!
+ stream.second->stream_reader()->RegisterCallback(base::Closure());
+ stream.second->set_finished(true);
+ }
+ }
+ can_recover_from_error = true;
+ }
+ }
+
+ SendUpdate(); // Make info up to date before error.
+
+ if (!can_recover_from_error) {
+ // Error case for both upstream source and file write.
+ // Shut down processing and signal an error to our observer.
+ // Our observer will clean us up.
+ 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
+ std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
+ 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
+ }
+}
+
DownloadFileImpl::RenameParameters::RenameParameters(
RenameOption option,
const base::FilePath& new_path,
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698