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

Side by Side Diff: content/browser/download/download_file_impl.cc

Issue 2794683002: set content length limit if half open range request fails (Closed)
Patch Set: Created 3 years, 8 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 unified diff | Download patch
OLDNEW
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 30 matching lines...) Expand all
41 // initial delay is specified by kInitialRenameRetryDelayMs. 41 // initial delay is specified by kInitialRenameRetryDelayMs.
42 const int kInitialRenameRetryDelayMs = 200; 42 const int kInitialRenameRetryDelayMs = 200;
43 43
44 // Number of times a failing rename is retried before giving up. 44 // Number of times a failing rename is retried before giving up.
45 const int kMaxRenameRetries = 3; 45 const int kMaxRenameRetries = 3;
46 46
47 // Because DownloadSaveInfo::kLengthFullContent is 0, we should avoid using 47 // Because DownloadSaveInfo::kLengthFullContent is 0, we should avoid using
48 // 0 for length if we found that a stream can no longer write any data. 48 // 0 for length if we found that a stream can no longer write any data.
49 const int kNoBytesToWrite = -1; 49 const int kNoBytesToWrite = -1;
50 50
51 // Default content length limit when the file size is not yet determined.
52 const int kUnknownContentLengthLimit = -1;
53
51 } // namespace 54 } // namespace
52 55
53 DownloadFileImpl::SourceStream::SourceStream( 56 DownloadFileImpl::SourceStream::SourceStream(
54 int64_t offset, 57 int64_t offset,
55 int64_t length, 58 int64_t length,
56 std::unique_ptr<ByteStreamReader> stream_reader) 59 std::unique_ptr<ByteStreamReader> stream_reader)
57 : offset_(offset), 60 : offset_(offset),
58 length_(length), 61 length_(length),
59 bytes_written_(0), 62 bytes_written_(0),
60 finished_(false), 63 finished_(false),
61 index_(0u), 64 index_(0u),
62 stream_reader_(std::move(stream_reader)) {} 65 stream_reader_(std::move(stream_reader)) {}
63 66
64 DownloadFileImpl::SourceStream::~SourceStream() = default; 67 DownloadFileImpl::SourceStream::~SourceStream() = default;
65 68
66 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { 69 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) {
67 bytes_written_ += bytes_write; 70 bytes_written_ += bytes_write;
68 } 71 }
69 72
70 void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock( 73 void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
71 int64_t offset, 74 int64_t offset,
72 int64_t bytes_written) { 75 int64_t bytes_written) {
73 DCHECK_GT(bytes_written, 0); 76 DCHECK_GT(bytes_written, 0);
74 if (length_ == kNoBytesToWrite) 77 if (length_ == kNoBytesToWrite)
75 return; 78 return;
76 79
77 if (offset <= offset_) { 80 if (offset <= offset_) {
78 if (offset + bytes_written > offset_) 81 if (offset + bytes_written > offset_) {
79 length_ = kNoBytesToWrite; 82 length_ = kNoBytesToWrite;
83 finished_ = true;
84 }
80 return; 85 return;
81 } 86 }
82 87
83 if (length_ == DownloadSaveInfo::kLengthFullContent || 88 if (length_ == DownloadSaveInfo::kLengthFullContent ||
84 length_ > offset - offset_) { 89 length_ > offset - offset_) {
85 length_ = offset - offset_; 90 length_ = offset - offset_;
86 } 91 }
87 } 92 }
88 93
89 DownloadFileImpl::DownloadFileImpl( 94 DownloadFileImpl::DownloadFileImpl(
90 std::unique_ptr<DownloadSaveInfo> save_info, 95 std::unique_ptr<DownloadSaveInfo> save_info,
91 const base::FilePath& default_download_directory, 96 const base::FilePath& default_download_directory,
92 std::unique_ptr<ByteStreamReader> stream_reader, 97 std::unique_ptr<ByteStreamReader> stream_reader,
93 const std::vector<DownloadItem::ReceivedSlice>& received_slices, 98 const std::vector<DownloadItem::ReceivedSlice>& received_slices,
94 const net::NetLogWithSource& download_item_net_log, 99 const net::NetLogWithSource& download_item_net_log,
95 base::WeakPtr<DownloadDestinationObserver> observer) 100 base::WeakPtr<DownloadDestinationObserver> observer)
96 : net_log_( 101 : net_log_(
97 net::NetLogWithSource::Make(download_item_net_log.net_log(), 102 net::NetLogWithSource::Make(download_item_net_log.net_log(),
98 net::NetLogSourceType::DOWNLOAD_FILE)), 103 net::NetLogSourceType::DOWNLOAD_FILE)),
99 file_(net_log_), 104 file_(net_log_),
100 save_info_(std::move(save_info)), 105 save_info_(std::move(save_info)),
101 default_download_directory_(default_download_directory), 106 default_download_directory_(default_download_directory),
107 content_length_limit_(kUnknownContentLengthLimit),
102 bytes_seen_(0), 108 bytes_seen_(0),
103 num_active_streams_(0), 109 num_active_streams_(0),
104 record_stream_bandwidth_(true), 110 record_stream_bandwidth_(true),
105 bytes_seen_with_parallel_streams_(0), 111 bytes_seen_with_parallel_streams_(0),
106 bytes_seen_without_parallel_streams_(0), 112 bytes_seen_without_parallel_streams_(0),
107 received_slices_(received_slices), 113 received_slices_(received_slices),
108 observer_(observer), 114 observer_(observer),
109 weak_factory_(this) { 115 weak_factory_(this) {
110 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>( 116 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>(
111 save_info_->offset, save_info_->length, std::move(stream_reader)); 117 save_info_->offset, save_info_->length, std::move(stream_reader));
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 343 }
338 344
339 void DownloadFileImpl::Detach() { 345 void DownloadFileImpl::Detach() {
340 file_.Detach(); 346 file_.Detach();
341 } 347 }
342 348
343 void DownloadFileImpl::Cancel() { 349 void DownloadFileImpl::Cancel() {
344 file_.Cancel(); 350 file_.Cancel();
345 } 351 }
346 352
353 void DownloadFileImpl::SetContentLengthLimit(int64_t limit) {
354 DCHECK(content_length_limit_ == limit ||
355 content_length_limit_ == kUnknownContentLengthLimit)
356 << "Content length changed, the download might have updated.";
xingliu 2017/03/31 23:38:21 nit%: Since content length is the size of the payl
qinmin 2017/04/01 05:20:01 Done.
357
358 if (limit < content_length_limit_ ||
359 content_length_limit_ == kUnknownContentLengthLimit) {
360 content_length_limit_ = limit;
xingliu 2017/03/31 23:38:21 Will we hit the DCHECK above when limit < content_
qinmin 2017/04/01 05:20:02 Yes, it will cause the DCHECK failure. The DCHECK
xingliu 2017/04/03 16:51:56 I see. sgtm.
361 }
362
363 // TODO(qinmin): interrupt the download if the received bytes are larger
364 // than content length limit.
365 LOG_IF(ERROR, TotalBytesReceived() > content_length_limit_)
366 << "Received data is larger than the content length limit.";
367 }
368
347 const base::FilePath& DownloadFileImpl::FullPath() const { 369 const base::FilePath& DownloadFileImpl::FullPath() const {
348 return file_.full_path(); 370 return file_.full_path();
349 } 371 }
350 372
351 bool DownloadFileImpl::InProgress() const { 373 bool DownloadFileImpl::InProgress() const {
352 return file_.in_progress(); 374 return file_.in_progress();
353 } 375 }
354 376
355 void DownloadFileImpl::WasPaused() { 377 void DownloadFileImpl::WasPaused() {
356 record_stream_bandwidth_ = false; 378 record_stream_bandwidth_ = false;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 461
440 RecordContiguousWriteTime(now - start); 462 RecordContiguousWriteTime(now - start);
441 463
442 // Take care of communication with our observer. 464 // Take care of communication with our observer.
443 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 465 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
444 HandleStreamError(source_stream, reason); 466 HandleStreamError(source_stream, reason);
445 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { 467 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) {
446 // Signal successful completion or termination of the current stream. 468 // Signal successful completion or termination of the current stream.
447 source_stream->stream_reader()->RegisterCallback(base::Closure()); 469 source_stream->stream_reader()->RegisterCallback(base::Closure());
448 source_stream->set_finished(true); 470 source_stream->set_finished(true);
471 if (source_stream->length() == DownloadSaveInfo::kLengthFullContent) {
472 SetContentLengthLimit(source_stream->offset() +
473 source_stream->bytes_written());
474 }
449 num_active_streams_--; 475 num_active_streams_--;
450 476
451 // Inform observers. 477 // Inform observers.
452 SendUpdate(); 478 SendUpdate();
453 479
454 // All the stream reader are completed, shut down file IO processing. 480 // All the stream reader are completed, shut down file IO processing.
455 if (IsDownloadCompleted()) { 481 if (IsDownloadCompleted()) {
456 RecordFileBandwidth(bytes_seen_, disk_writes_time_, 482 RecordFileBandwidth(bytes_seen_, disk_writes_time_,
457 base::TimeTicks::Now() - download_start_); 483 base::TimeTicks::Now() - download_start_);
458 if (IsSparseFile() && record_stream_bandwidth_) { 484 if (IsSparseFile() && record_stream_bandwidth_) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 source_stream->set_index(source_stream->index() + 1); 567 source_stream->set_index(source_stream->index() + 1);
542 } else if (source_stream->offset() == offset) { 568 } else if (source_stream->offset() == offset) {
543 source_stream->set_index(index); 569 source_stream->set_index(index);
544 } else { 570 } else {
545 source_stream->TruncateLengthWithWrittenDataBlock(offset, length); 571 source_stream->TruncateLengthWithWrittenDataBlock(offset, length);
546 } 572 }
547 } 573 }
548 } 574 }
549 575
550 bool DownloadFileImpl::IsDownloadCompleted() { 576 bool DownloadFileImpl::IsDownloadCompleted() {
551 SourceStream* stream_for_last_slice = nullptr;
552 int64_t last_slice_offset = 0;
553 for (auto& stream : source_streams_) { 577 for (auto& stream : source_streams_) {
554 SourceStream* source_stream = stream.second.get(); 578 if (!stream.second->is_finished())
555 if (source_stream->offset() >= last_slice_offset &&
556 source_stream->bytes_written() > 0) {
557 stream_for_last_slice = source_stream;
558 last_slice_offset = source_stream->offset();
559 }
560 if (!source_stream->is_finished())
561 return false; 579 return false;
562 } 580 }
563 581
564 if (!IsSparseFile()) 582 if (!IsSparseFile())
565 return true; 583 return true;
566 584
567 // Verify that all the file slices have been downloaded. 585 // Verify that all the file slices have been downloaded.
568 std::vector<DownloadItem::ReceivedSlice> slices_to_download = 586 std::vector<DownloadItem::ReceivedSlice> slices_to_download =
569 FindSlicesToDownload(received_slices_); 587 FindSlicesToDownload(received_slices_);
570 if (slices_to_download.size() > 1) { 588 if (slices_to_download.size() > 1) {
571 // If there are 1 or more holes in the file, download is not finished. 589 // If there are 1 or more holes in the file, download is not finished.
572 // Some streams might not have been added to |source_streams_| yet. 590 // Some streams might not have been added to |source_streams_| yet.
573 return false; 591 return false;
574 } 592 }
575 if (stream_for_last_slice) { 593 return TotalBytesReceived() == content_length_limit_;
576 DCHECK_EQ(slices_to_download[0].received_bytes,
577 DownloadSaveInfo::kLengthFullContent);
578 // The last stream should not have a length limit. If it has, it might
579 // not reach the end of the file.
580 if (stream_for_last_slice->length() !=
581 DownloadSaveInfo::kLengthFullContent) {
582 return false;
583 }
584 DCHECK_EQ(slices_to_download[0].offset,
585 stream_for_last_slice->offset() +
586 stream_for_last_slice->bytes_written());
587 }
588
589 return true;
590 } 594 }
591 595
592 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, 596 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
593 DownloadInterruptReason reason) { 597 DownloadInterruptReason reason) {
594 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 598 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
595 source_stream->stream_reader()->RegisterCallback(base::Closure()); 599 source_stream->stream_reader()->RegisterCallback(base::Closure());
596 source_stream->set_finished(true); 600 source_stream->set_finished(true);
597 num_active_streams_--; 601 num_active_streams_--;
598 602
599 bool can_recover_from_error = false; 603 bool can_recover_from_error = false;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 const base::FilePath& new_path, 697 const base::FilePath& new_path,
694 const RenameCompletionCallback& completion_callback) 698 const RenameCompletionCallback& completion_callback)
695 : option(option), 699 : option(option),
696 new_path(new_path), 700 new_path(new_path),
697 retries_left(kMaxRenameRetries), 701 retries_left(kMaxRenameRetries),
698 completion_callback(completion_callback) {} 702 completion_callback(completion_callback) {}
699 703
700 DownloadFileImpl::RenameParameters::~RenameParameters() {} 704 DownloadFileImpl::RenameParameters::~RenameParameters() {}
701 705
702 } // namespace content 706 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698