| 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 24 matching lines...) Expand all Loading... |
| 35 const int kMaxTimeBlockingFileThreadMs = 1000; | 35 const int kMaxTimeBlockingFileThreadMs = 1000; |
| 36 | 36 |
| 37 // These constants control the default retry behavior for failing renames. Each | 37 // These constants control the default retry behavior for failing renames. Each |
| 38 // retry is performed after a delay that is twice the previous delay. The | 38 // retry is performed after a delay that is twice the previous delay. The |
| 39 // initial delay is specified by kInitialRenameRetryDelayMs. | 39 // initial delay is specified by kInitialRenameRetryDelayMs. |
| 40 const int kInitialRenameRetryDelayMs = 200; | 40 const int kInitialRenameRetryDelayMs = 200; |
| 41 | 41 |
| 42 // Number of times a failing rename is retried before giving up. | 42 // Number of times a failing rename is retried before giving up. |
| 43 const int kMaxRenameRetries = 3; | 43 const int kMaxRenameRetries = 3; |
| 44 | 44 |
| 45 DownloadFileImpl::SourceStream::SourceStream(int64_t offset, int64_t length) | 45 DownloadFileImpl::SourceStream::SourceStream( |
| 46 int64_t offset, |
| 47 int64_t length, |
| 48 std::unique_ptr<ByteStreamReader> stream_reader) |
| 46 : offset_(offset), | 49 : offset_(offset), |
| 47 length_(length), | 50 length_(length), |
| 48 bytes_written_(0), | 51 bytes_written_(0), |
| 49 finished_(false), | 52 finished_(false), |
| 50 index_(0u) {} | 53 index_(0u), |
| 54 stream_reader_(std::move(stream_reader)) {} |
| 51 | 55 |
| 52 DownloadFileImpl::SourceStream::~SourceStream() = default; | 56 DownloadFileImpl::SourceStream::~SourceStream() = default; |
| 53 | 57 |
| 54 void DownloadFileImpl::SourceStream::SetByteStream( | |
| 55 std::unique_ptr<ByteStreamReader> stream_reader) { | |
| 56 stream_reader_ = std::move(stream_reader); | |
| 57 } | |
| 58 | |
| 59 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { | 58 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { |
| 60 bytes_written_ += bytes_write; | 59 bytes_written_ += bytes_write; |
| 61 } | 60 } |
| 62 | 61 |
| 63 DownloadFileImpl::DownloadFileImpl( | 62 DownloadFileImpl::DownloadFileImpl( |
| 64 std::unique_ptr<DownloadSaveInfo> save_info, | 63 std::unique_ptr<DownloadSaveInfo> save_info, |
| 65 const base::FilePath& default_download_directory, | 64 const base::FilePath& default_download_directory, |
| 66 std::unique_ptr<ByteStreamReader> stream_reader, | 65 std::unique_ptr<ByteStreamReader> stream_reader, |
| 67 const std::vector<DownloadItem::ReceivedSlice>& received_slices, | 66 const std::vector<DownloadItem::ReceivedSlice>& received_slices, |
| 68 const net::NetLogWithSource& download_item_net_log, | 67 const net::NetLogWithSource& download_item_net_log, |
| 69 bool is_sparse_file, | 68 bool is_sparse_file, |
| 70 base::WeakPtr<DownloadDestinationObserver> observer) | 69 base::WeakPtr<DownloadDestinationObserver> observer) |
| 71 : net_log_( | 70 : net_log_( |
| 72 net::NetLogWithSource::Make(download_item_net_log.net_log(), | 71 net::NetLogWithSource::Make(download_item_net_log.net_log(), |
| 73 net::NetLogSourceType::DOWNLOAD_FILE)), | 72 net::NetLogSourceType::DOWNLOAD_FILE)), |
| 74 file_(net_log_), | 73 file_(net_log_), |
| 75 save_info_(std::move(save_info)), | 74 save_info_(std::move(save_info)), |
| 76 default_download_directory_(default_download_directory), | 75 default_download_directory_(default_download_directory), |
| 77 is_sparse_file_(is_sparse_file), | 76 is_sparse_file_(is_sparse_file), |
| 78 bytes_seen_(0), | 77 bytes_seen_(0), |
| 79 received_slices_(received_slices), | 78 received_slices_(received_slices), |
| 80 observer_(observer), | 79 observer_(observer), |
| 81 weak_factory_(this) { | 80 weak_factory_(this) { |
| 82 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>( | 81 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>( |
| 83 save_info_->offset, DownloadSaveInfo::kLengthFullContent); | 82 save_info_->offset, save_info_->length, std::move(stream_reader)); |
| 84 DCHECK(source_streams_.size() == static_cast<size_t>(1)); | |
| 85 source_streams_[save_info_->offset]->SetByteStream(std::move(stream_reader)); | |
| 86 | 83 |
| 87 download_item_net_log.AddEvent( | 84 download_item_net_log.AddEvent( |
| 88 net::NetLogEventType::DOWNLOAD_FILE_CREATED, | 85 net::NetLogEventType::DOWNLOAD_FILE_CREATED, |
| 89 net_log_.source().ToEventParametersCallback()); | 86 net_log_.source().ToEventParametersCallback()); |
| 90 net_log_.BeginEvent( | 87 net_log_.BeginEvent( |
| 91 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, | 88 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, |
| 92 download_item_net_log.source().ToEventParametersCallback()); | 89 download_item_net_log.source().ToEventParametersCallback()); |
| 93 } | 90 } |
| 94 | 91 |
| 95 DownloadFileImpl::~DownloadFileImpl() { | 92 DownloadFileImpl::~DownloadFileImpl() { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 118 BrowserThread::PostTask( | 115 BrowserThread::PostTask( |
| 119 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); | 116 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); |
| 120 return; | 117 return; |
| 121 } | 118 } |
| 122 | 119 |
| 123 download_start_ = base::TimeTicks::Now(); | 120 download_start_ = base::TimeTicks::Now(); |
| 124 | 121 |
| 125 // Primarily to make reset to zero in restart visible to owner. | 122 // Primarily to make reset to zero in restart visible to owner. |
| 126 SendUpdate(); | 123 SendUpdate(); |
| 127 | 124 |
| 128 // Initial pull from the straw. | |
| 129 for (auto& source_stream : source_streams_) | |
| 130 RegisterAndActivateStream(source_stream.second.get()); | |
| 131 | |
| 132 BrowserThread::PostTask( | 125 BrowserThread::PostTask( |
| 133 BrowserThread::UI, FROM_HERE, base::Bind( | 126 BrowserThread::UI, FROM_HERE, base::Bind( |
| 134 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); | 127 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); |
| 128 |
| 129 // Initial pull from the straw from all source streams. |
| 130 for (auto& source_stream : source_streams_) |
| 131 RegisterAndActivateStream(source_stream.second.get()); |
| 135 } | 132 } |
| 136 | 133 |
| 137 void DownloadFileImpl::AddByteStream( | 134 void DownloadFileImpl::AddByteStream( |
| 138 std::unique_ptr<ByteStreamReader> stream_reader, | 135 std::unique_ptr<ByteStreamReader> stream_reader, |
| 139 int64_t offset) { | 136 int64_t offset, |
| 137 int64_t length) { |
| 140 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 138 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 141 | 139 |
| 142 // The |source_streams_| must have an existing entry for the stream reader. | 140 source_streams_[offset] = |
| 143 auto current_source_stream = source_streams_.find(offset); | 141 base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader)); |
| 144 DCHECK(current_source_stream != source_streams_.end()); | |
| 145 SourceStream* stream = current_source_stream->second.get(); | |
| 146 stream->SetByteStream(std::move(stream_reader)); | |
| 147 | 142 |
| 148 RegisterAndActivateStream(stream); | 143 // If the file is initialized, start to write data, or wait until file opened. |
| 144 if (file_.in_progress()) |
| 145 RegisterAndActivateStream(source_streams_[offset].get()); |
| 149 } | 146 } |
| 150 | 147 |
| 151 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, | 148 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, |
| 152 const char* data, | 149 const char* data, |
| 153 size_t data_len) { | 150 size_t data_len) { |
| 154 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 151 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 155 WillWriteToDisk(data_len); | 152 WillWriteToDisk(data_len); |
| 156 return file_.WriteDataToFile(offset, data, data_len); | 153 return file_.WriteDataToFile(offset, data, data_len); |
| 157 } | 154 } |
| 158 | 155 |
| 159 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, | 156 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, |
| 160 size_t bytes_available_to_write, | 157 size_t bytes_available_to_write, |
| 161 size_t* bytes_to_write) { | 158 size_t* bytes_to_write) { |
| 162 // If a new slice finds that its target position has already been written, | 159 // If a new slice finds that its target position has already been written, |
| 163 // terminate the stream. | 160 // terminate the stream. |
| 164 if (source_stream->bytes_written() == 0) { | 161 if (source_stream->bytes_written() == 0) { |
| 165 for (const auto& received_slice : received_slices_) { | 162 for (const auto& received_slice : received_slices_) { |
| 166 if (received_slice.offset <= source_stream->offset() && | 163 if (received_slice.offset <= source_stream->offset() && |
| 167 received_slice.offset + received_slice.received_bytes > | 164 received_slice.offset + received_slice.received_bytes > |
| 168 source_stream->offset()) { | 165 source_stream->offset()) { |
| 169 *bytes_to_write = 0; | 166 *bytes_to_write = 0; |
| 170 return true; | 167 return true; |
| 171 } | 168 } |
| 172 } | 169 } |
| 173 } | 170 } |
| 174 | 171 |
| 175 if (source_stream->length() != DownloadSaveInfo::kLengthFullContent && | 172 if (source_stream->length() != DownloadSaveInfo::kLengthFullContent && |
| 176 source_stream->bytes_written() + | 173 source_stream->bytes_written() + |
| 177 static_cast<int64_t>(bytes_available_to_write) >= | 174 static_cast<int64_t>(bytes_available_to_write) > |
| 178 source_stream->length()) { | 175 source_stream->length()) { |
| 179 // Write a partial buffer as the incoming data exceeds the length limit. | 176 // Write a partial buffer as the incoming data exceeds the length limit. |
| 180 *bytes_to_write = source_stream->length() - source_stream->bytes_written(); | 177 *bytes_to_write = source_stream->length() - source_stream->bytes_written(); |
| 181 return true; | 178 return true; |
| 182 } | 179 } |
| 183 | 180 |
| 184 *bytes_to_write = bytes_available_to_write; | 181 *bytes_to_write = bytes_available_to_write; |
| 185 return false; | 182 return false; |
| 186 } | 183 } |
| 187 | 184 |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 const base::FilePath& new_path, | 541 const base::FilePath& new_path, |
| 545 const RenameCompletionCallback& completion_callback) | 542 const RenameCompletionCallback& completion_callback) |
| 546 : option(option), | 543 : option(option), |
| 547 new_path(new_path), | 544 new_path(new_path), |
| 548 retries_left(kMaxRenameRetries), | 545 retries_left(kMaxRenameRetries), |
| 549 completion_callback(completion_callback) {} | 546 completion_callback(completion_callback) {} |
| 550 | 547 |
| 551 DownloadFileImpl::RenameParameters::~RenameParameters() {} | 548 DownloadFileImpl::RenameParameters::~RenameParameters() {} |
| 552 | 549 |
| 553 } // namespace content | 550 } // namespace content |
| OLD | NEW |