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" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/memory/ptr_util.h" | |
| 12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 13 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "content/browser/byte_stream.h" | 16 #include "content/browser/byte_stream.h" |
| 16 #include "content/browser/download/download_create_info.h" | 17 #include "content/browser/download/download_create_info.h" |
| 17 #include "content/browser/download/download_destination_observer.h" | 18 #include "content/browser/download/download_destination_observer.h" |
| 18 #include "content/browser/download/download_interrupt_reasons_impl.h" | 19 #include "content/browser/download/download_interrupt_reasons_impl.h" |
| 19 #include "content/browser/download/download_net_log_parameters.h" | 20 #include "content/browser/download/download_net_log_parameters.h" |
| 20 #include "content/browser/download/download_stats.h" | 21 #include "content/browser/download/download_stats.h" |
| 21 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 33 const int kMaxTimeBlockingFileThreadMs = 1000; | 34 const int kMaxTimeBlockingFileThreadMs = 1000; |
| 34 | 35 |
| 35 // These constants control the default retry behavior for failing renames. Each | 36 // These constants control the default retry behavior for failing renames. Each |
| 36 // retry is performed after a delay that is twice the previous delay. The | 37 // retry is performed after a delay that is twice the previous delay. The |
| 37 // initial delay is specified by kInitialRenameRetryDelayMs. | 38 // initial delay is specified by kInitialRenameRetryDelayMs. |
| 38 const int kInitialRenameRetryDelayMs = 200; | 39 const int kInitialRenameRetryDelayMs = 200; |
| 39 | 40 |
| 40 // Number of times a failing rename is retried before giving up. | 41 // Number of times a failing rename is retried before giving up. |
| 41 const int kMaxRenameRetries = 3; | 42 const int kMaxRenameRetries = 3; |
| 42 | 43 |
| 44 DownloadFileImpl::SourceStream::SourceStream(int64_t offset, | |
| 45 int64_t bytes_received) | |
| 46 : offset_(offset), bytes_received_(bytes_received), finished_(false) {} | |
| 47 | |
| 48 DownloadFileImpl::SourceStream::~SourceStream() = default; | |
| 49 | |
| 50 void DownloadFileImpl::SourceStream::SetByteStream( | |
| 51 std::unique_ptr<ByteStreamReader> stream_reader) { | |
| 52 stream_reader_ = std::move(stream_reader); | |
| 53 } | |
| 54 | |
| 55 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { | |
| 56 bytes_received_ += bytes_write; | |
| 57 } | |
| 58 | |
| 43 DownloadFileImpl::DownloadFileImpl( | 59 DownloadFileImpl::DownloadFileImpl( |
| 44 std::unique_ptr<DownloadSaveInfo> save_info, | 60 std::unique_ptr<DownloadSaveInfo> save_info, |
| 45 const base::FilePath& default_download_directory, | 61 const base::FilePath& default_download_directory, |
| 46 std::unique_ptr<ByteStreamReader> stream, | 62 std::unique_ptr<ByteStreamReader> stream_reader, |
| 47 const net::NetLogWithSource& download_item_net_log, | 63 const net::NetLogWithSource& download_item_net_log, |
| 64 bool is_sparse_file, | |
| 48 base::WeakPtr<DownloadDestinationObserver> observer) | 65 base::WeakPtr<DownloadDestinationObserver> observer) |
| 49 : net_log_( | 66 : net_log_( |
| 50 net::NetLogWithSource::Make(download_item_net_log.net_log(), | 67 net::NetLogWithSource::Make(download_item_net_log.net_log(), |
| 51 net::NetLogSourceType::DOWNLOAD_FILE)), | 68 net::NetLogSourceType::DOWNLOAD_FILE)), |
| 52 file_(net_log_), | 69 file_(net_log_), |
| 53 save_info_(std::move(save_info)), | 70 save_info_(std::move(save_info)), |
| 54 default_download_directory_(default_download_directory), | 71 default_download_directory_(default_download_directory), |
| 55 stream_reader_(std::move(stream)), | 72 is_sparse_file_(is_sparse_file), |
| 56 bytes_seen_(0), | 73 bytes_seen_(0), |
| 57 observer_(observer), | 74 observer_(observer), |
| 58 weak_factory_(this) { | 75 weak_factory_(this) { |
| 76 source_streams_[save_info_->offset] = | |
| 77 base::MakeUnique<SourceStream>(save_info_->offset, 0); | |
| 78 DCHECK(source_streams_.size() == static_cast<size_t>(1)); | |
| 79 source_streams_.begin()->second->SetByteStream(std::move(stream_reader)); | |
| 80 | |
| 59 download_item_net_log.AddEvent( | 81 download_item_net_log.AddEvent( |
| 60 net::NetLogEventType::DOWNLOAD_FILE_CREATED, | 82 net::NetLogEventType::DOWNLOAD_FILE_CREATED, |
| 61 net_log_.source().ToEventParametersCallback()); | 83 net_log_.source().ToEventParametersCallback()); |
| 62 net_log_.BeginEvent( | 84 net_log_.BeginEvent( |
| 63 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, | 85 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, |
| 64 download_item_net_log.source().ToEventParametersCallback()); | 86 download_item_net_log.source().ToEventParametersCallback()); |
| 65 } | 87 } |
| 66 | 88 |
| 67 DownloadFileImpl::~DownloadFileImpl() { | 89 DownloadFileImpl::~DownloadFileImpl() { |
| 68 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 69 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE); | 91 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE); |
| 70 } | 92 } |
| 71 | 93 |
| 72 void DownloadFileImpl::Initialize(const InitializeCallback& callback) { | 94 void DownloadFileImpl::Initialize(const InitializeCallback& callback) { |
| 73 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 95 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 74 | 96 |
| 75 update_timer_.reset(new base::RepeatingTimer()); | 97 update_timer_.reset(new base::RepeatingTimer()); |
| 76 DownloadInterruptReason result = | 98 DownloadInterruptReason result = |
| 77 file_.Initialize(save_info_->file_path, | 99 file_.Initialize(save_info_->file_path, default_download_directory_, |
| 78 default_download_directory_, | 100 std::move(save_info_->file), save_info_->offset, |
| 79 std::move(save_info_->file), | |
| 80 save_info_->offset, | |
| 81 save_info_->hash_of_partial_file, | 101 save_info_->hash_of_partial_file, |
| 82 std::move(save_info_->hash_state), | 102 std::move(save_info_->hash_state), is_sparse_file_); |
| 83 false); | |
| 84 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { | 103 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 85 BrowserThread::PostTask( | 104 BrowserThread::PostTask( |
| 86 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); | 105 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); |
| 87 return; | 106 return; |
| 88 } | 107 } |
| 89 | 108 |
| 90 stream_reader_->RegisterCallback( | |
| 91 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr())); | |
| 92 | |
| 93 download_start_ = base::TimeTicks::Now(); | 109 download_start_ = base::TimeTicks::Now(); |
| 94 | 110 |
| 95 // Primarily to make reset to zero in restart visible to owner. | 111 // Primarily to make reset to zero in restart visible to owner. |
| 96 SendUpdate(); | 112 SendUpdate(); |
| 97 | 113 |
| 98 // Initial pull from the straw. | 114 // Initial pull from the straw. |
| 99 StreamActive(); | 115 for (auto& source_stream : source_streams_) { |
|
qinmin
2017/02/27 18:55:29
no {} needed
xingliu
2017/02/28 00:57:06
Done.
| |
| 116 RegisterAndActivateStream(source_stream.second.get()); | |
| 117 } | |
| 100 | 118 |
| 101 BrowserThread::PostTask( | 119 BrowserThread::PostTask( |
| 102 BrowserThread::UI, FROM_HERE, base::Bind( | 120 BrowserThread::UI, FROM_HERE, base::Bind( |
| 103 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); | 121 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); |
| 104 } | 122 } |
| 105 | 123 |
| 124 void DownloadFileImpl::AddByteStream( | |
| 125 std::unique_ptr<ByteStreamReader> stream_reader, | |
| 126 int64_t offset) { | |
| 127 // |source_streams_| is not thread safe, must be modified on the same thread. | |
| 128 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 129 | |
| 130 // The |source_streams_| must have an existing entry for the stream reader. | |
| 131 auto current_source_stream = source_streams_.find(offset); | |
| 132 DCHECK(current_source_stream != source_streams_.end()); | |
| 133 SourceStream* stream = current_source_stream->second.get(); | |
| 134 stream->SetByteStream(std::move(stream_reader)); | |
| 135 | |
| 136 // Start to pull data from the stream. | |
| 137 BrowserThread::PostTask( | |
| 138 BrowserThread::FILE, FROM_HERE, | |
| 139 base::Bind(&DownloadFileImpl::RegisterAndActivateStream, | |
| 140 weak_factory_.GetWeakPtr(), stream)); | |
| 141 } | |
| 142 | |
| 106 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( | 143 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( |
| 107 const char* data, size_t data_len) { | 144 const char* data, size_t data_len) { |
| 108 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 145 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 146 WillWriteToDisk(data_len); | |
| 147 return file_.AppendDataToFile(data, data_len); | |
| 148 } | |
| 109 | 149 |
| 110 if (!update_timer_->IsRunning()) { | 150 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, |
| 111 update_timer_->Start(FROM_HERE, | 151 const char* data, |
| 112 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 152 size_t data_len) { |
| 113 this, &DownloadFileImpl::SendUpdate); | 153 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 114 } | 154 WillWriteToDisk(data_len); |
| 115 rate_estimator_.Increment(data_len); | 155 return file_.WriteDataToFile(offset, data, data_len); |
| 116 return file_.AppendDataToFile(data, data_len); | |
| 117 } | 156 } |
| 118 | 157 |
| 119 void DownloadFileImpl::RenameAndUniquify( | 158 void DownloadFileImpl::RenameAndUniquify( |
| 120 const base::FilePath& full_path, | 159 const base::FilePath& full_path, |
| 121 const RenameCompletionCallback& callback) { | 160 const RenameCompletionCallback& callback) { |
| 122 std::unique_ptr<RenameParameters> parameters( | 161 std::unique_ptr<RenameParameters> parameters( |
| 123 new RenameParameters(UNIQUIFY, full_path, callback)); | 162 new RenameParameters(UNIQUIFY, full_path, callback)); |
| 124 RenameWithRetryInternal(std::move(parameters)); | 163 RenameWithRetryInternal(std::move(parameters)); |
| 125 } | 164 } |
| 126 | 165 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 parameters->source_url, | 245 parameters->source_url, |
| 207 parameters->referrer_url); | 246 parameters->referrer_url); |
| 208 } | 247 } |
| 209 | 248 |
| 210 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 249 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 211 // Make sure our information is updated, since we're about to | 250 // Make sure our information is updated, since we're about to |
| 212 // error out. | 251 // error out. |
| 213 SendUpdate(); | 252 SendUpdate(); |
| 214 | 253 |
| 215 // Null out callback so that we don't do any more stream processing. | 254 // Null out callback so that we don't do any more stream processing. |
| 216 stream_reader_->RegisterCallback(base::Closure()); | 255 for (auto& stream : source_streams_) { |
| 256 ByteStreamReader* stream_reader = stream.second->stream_reader(); | |
| 257 if (stream_reader) | |
|
qinmin
2017/02/27 18:55:29
no {}
xingliu
2017/02/28 00:57:06
Done. Kept {} here since there are multiple lines.
| |
| 258 stream_reader->RegisterCallback(base::Closure()); | |
| 259 } | |
| 217 | 260 |
| 218 new_path.clear(); | 261 new_path.clear(); |
| 219 } | 262 } |
| 220 | 263 |
| 221 BrowserThread::PostTask( | 264 BrowserThread::PostTask( |
| 222 BrowserThread::UI, | 265 BrowserThread::UI, |
| 223 FROM_HERE, | 266 FROM_HERE, |
| 224 base::Bind(parameters->completion_callback, reason, new_path)); | 267 base::Bind(parameters->completion_callback, reason, new_path)); |
| 225 } | 268 } |
| 226 | 269 |
| 227 void DownloadFileImpl::Detach() { | 270 void DownloadFileImpl::Detach() { |
| 228 file_.Detach(); | 271 file_.Detach(); |
| 229 } | 272 } |
| 230 | 273 |
| 231 void DownloadFileImpl::Cancel() { | 274 void DownloadFileImpl::Cancel() { |
| 232 file_.Cancel(); | 275 file_.Cancel(); |
| 233 } | 276 } |
| 234 | 277 |
| 235 const base::FilePath& DownloadFileImpl::FullPath() const { | 278 const base::FilePath& DownloadFileImpl::FullPath() const { |
| 236 return file_.full_path(); | 279 return file_.full_path(); |
| 237 } | 280 } |
| 238 | 281 |
| 239 bool DownloadFileImpl::InProgress() const { | 282 bool DownloadFileImpl::InProgress() const { |
| 240 return file_.in_progress(); | 283 return file_.in_progress(); |
| 241 } | 284 } |
| 242 | 285 |
| 243 void DownloadFileImpl::StreamActive() { | 286 void DownloadFileImpl::StreamActive(SourceStream* source_stream) { |
| 287 DCHECK(source_stream->stream_reader()); | |
| 244 base::TimeTicks start(base::TimeTicks::Now()); | 288 base::TimeTicks start(base::TimeTicks::Now()); |
| 245 base::TimeTicks now; | 289 base::TimeTicks now; |
| 246 scoped_refptr<net::IOBuffer> incoming_data; | 290 scoped_refptr<net::IOBuffer> incoming_data; |
| 247 size_t incoming_data_size = 0; | 291 size_t incoming_data_size = 0; |
| 248 size_t total_incoming_data_size = 0; | 292 size_t total_incoming_data_size = 0; |
| 249 size_t num_buffers = 0; | 293 size_t num_buffers = 0; |
| 250 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); | 294 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); |
| 251 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; | 295 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 252 base::TimeDelta delta( | 296 base::TimeDelta delta( |
| 253 base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs)); | 297 base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs)); |
| 254 | 298 |
| 255 // Take care of any file local activity required. | 299 // Take care of any file local activity required. |
| 256 do { | 300 do { |
| 257 state = stream_reader_->Read(&incoming_data, &incoming_data_size); | 301 state = source_stream->stream_reader()->Read(&incoming_data, |
| 302 &incoming_data_size); | |
| 258 | 303 |
| 259 switch (state) { | 304 switch (state) { |
| 260 case ByteStreamReader::STREAM_EMPTY: | 305 case ByteStreamReader::STREAM_EMPTY: |
| 261 break; | 306 break; |
| 262 case ByteStreamReader::STREAM_HAS_DATA: | 307 case ByteStreamReader::STREAM_HAS_DATA: |
| 263 { | 308 { |
| 264 ++num_buffers; | 309 ++num_buffers; |
| 265 base::TimeTicks write_start(base::TimeTicks::Now()); | 310 base::TimeTicks write_start(base::TimeTicks::Now()); |
| 266 reason = AppendDataToFile( | 311 if (is_sparse_file_) { |
| 267 incoming_data.get()->data(), incoming_data_size); | 312 reason = WriteDataToFile( |
| 313 source_stream->offset() + source_stream->bytes_received(), | |
| 314 incoming_data.get()->data(), incoming_data_size); | |
| 315 } else { | |
| 316 reason = AppendDataToFile(incoming_data.get()->data(), | |
| 317 incoming_data_size); | |
| 318 } | |
| 268 disk_writes_time_ += (base::TimeTicks::Now() - write_start); | 319 disk_writes_time_ += (base::TimeTicks::Now() - write_start); |
| 269 bytes_seen_ += incoming_data_size; | 320 bytes_seen_ += incoming_data_size; |
| 270 total_incoming_data_size += incoming_data_size; | 321 total_incoming_data_size += incoming_data_size; |
| 322 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) | |
| 323 source_stream->OnWriteBytesToDisk(incoming_data_size); | |
| 271 } | 324 } |
| 272 break; | 325 break; |
| 273 case ByteStreamReader::STREAM_COMPLETE: | 326 case ByteStreamReader::STREAM_COMPLETE: |
| 274 { | 327 { |
| 275 reason = static_cast<DownloadInterruptReason>( | 328 reason = static_cast<DownloadInterruptReason>( |
|
qinmin
2017/02/27 18:55:29
fix the indentations
xingliu
2017/02/28 00:57:06
Done.
| |
| 276 stream_reader_->GetStatus()); | 329 source_stream->stream_reader()->GetStatus()); |
| 277 SendUpdate(); | 330 SendUpdate(); |
| 278 base::TimeTicks close_start(base::TimeTicks::Now()); | |
| 279 base::TimeTicks now(base::TimeTicks::Now()); | |
| 280 disk_writes_time_ += (now - close_start); | |
| 281 RecordFileBandwidth( | |
| 282 bytes_seen_, disk_writes_time_, now - download_start_); | |
| 283 update_timer_.reset(); | |
| 284 } | 331 } |
| 285 break; | 332 break; |
| 286 default: | 333 default: |
| 287 NOTREACHED(); | 334 NOTREACHED(); |
| 288 break; | 335 break; |
| 289 } | 336 } |
| 290 now = base::TimeTicks::Now(); | 337 now = base::TimeTicks::Now(); |
| 291 } while (state == ByteStreamReader::STREAM_HAS_DATA && | 338 } while (state == ByteStreamReader::STREAM_HAS_DATA && |
| 292 reason == DOWNLOAD_INTERRUPT_REASON_NONE && | 339 reason == DOWNLOAD_INTERRUPT_REASON_NONE && |
| 293 now - start <= delta); | 340 now - start <= delta); |
| 294 | 341 |
| 295 // If we're stopping to yield the thread, post a task so we come back. | 342 // If we're stopping to yield the thread, post a task so we come back. |
| 296 if (state == ByteStreamReader::STREAM_HAS_DATA && | 343 if (state == ByteStreamReader::STREAM_HAS_DATA && |
| 297 now - start > delta) { | 344 now - start > delta) { |
| 298 BrowserThread::PostTask( | 345 BrowserThread::PostTask( |
| 299 BrowserThread::FILE, FROM_HERE, | 346 BrowserThread::FILE, FROM_HERE, |
| 300 base::Bind(&DownloadFileImpl::StreamActive, | 347 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), |
| 301 weak_factory_.GetWeakPtr())); | 348 source_stream)); |
| 302 } | 349 } |
| 303 | 350 |
| 304 if (total_incoming_data_size) | 351 if (total_incoming_data_size) |
| 305 RecordFileThreadReceiveBuffers(num_buffers); | 352 RecordFileThreadReceiveBuffers(num_buffers); |
| 306 | 353 |
| 307 RecordContiguousWriteTime(now - start); | 354 RecordContiguousWriteTime(now - start); |
| 308 | 355 |
| 309 // Take care of communication with our observer. | 356 // Take care of communication with our observer. |
| 310 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 357 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 358 if (state == ByteStreamReader::STREAM_COMPLETE) { | |
| 359 RecordFileBandwidth(bytes_seen_, disk_writes_time_, | |
| 360 base::TimeTicks::Now() - download_start_); | |
| 361 } | |
| 311 // Error case for both upstream source and file write. | 362 // Error case for both upstream source and file write. |
| 312 // Shut down processing and signal an error to our observer. | 363 // Shut down processing and signal an error to our observer. |
| 313 // Our observer will clean us up. | 364 // Our observer will clean us up. |
| 314 stream_reader_->RegisterCallback(base::Closure()); | 365 source_stream->stream_reader()->RegisterCallback(base::Closure()); |
| 315 weak_factory_.InvalidateWeakPtrs(); | 366 weak_factory_.InvalidateWeakPtrs(); |
| 316 SendUpdate(); // Make info up to date before error. | 367 SendUpdate(); // Make info up to date before error. |
| 317 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | 368 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); |
| 318 BrowserThread::PostTask( | 369 BrowserThread::PostTask( |
| 319 BrowserThread::UI, | 370 BrowserThread::UI, FROM_HERE, |
| 320 FROM_HERE, | 371 base::Bind(&DownloadDestinationObserver::DestinationError, observer_, |
| 321 base::Bind(&DownloadDestinationObserver::DestinationError, | 372 reason, TotalBytesReceived(), base::Passed(&hash_state))); |
| 322 observer_, | |
| 323 reason, | |
| 324 file_.bytes_so_far(), | |
| 325 base::Passed(&hash_state))); | |
| 326 } else if (state == ByteStreamReader::STREAM_COMPLETE) { | 373 } else if (state == ByteStreamReader::STREAM_COMPLETE) { |
| 327 // Signal successful completion and shut down processing. | 374 // Signal successful completion of the current stream. |
| 328 stream_reader_->RegisterCallback(base::Closure()); | 375 source_stream->stream_reader()->RegisterCallback(base::Closure()); |
| 329 weak_factory_.InvalidateWeakPtrs(); | 376 source_stream->set_finished(true); |
| 377 | |
| 378 // Inform observers. | |
| 330 SendUpdate(); | 379 SendUpdate(); |
| 331 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | 380 |
| 332 BrowserThread::PostTask( | 381 bool all_stream_complete = true; |
| 333 BrowserThread::UI, | 382 for (auto& stream : source_streams_) { |
| 334 FROM_HERE, | 383 if (!stream.second->is_finished()) { |
| 335 base::Bind(&DownloadDestinationObserver::DestinationCompleted, | 384 all_stream_complete = false; |
| 336 observer_, | 385 break; |
| 337 file_.bytes_so_far(), | 386 } |
| 338 base::Passed(&hash_state))); | 387 } |
| 388 | |
| 389 // All the stream reader are completed, shut down file IO processing. | |
| 390 if (all_stream_complete) { | |
| 391 RecordFileBandwidth(bytes_seen_, disk_writes_time_, | |
| 392 base::TimeTicks::Now() - download_start_); | |
| 393 weak_factory_.InvalidateWeakPtrs(); | |
| 394 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | |
| 395 update_timer_.reset(); | |
| 396 BrowserThread::PostTask( | |
| 397 BrowserThread::UI, FROM_HERE, | |
| 398 base::Bind(&DownloadDestinationObserver::DestinationCompleted, | |
| 399 observer_, TotalBytesReceived(), | |
| 400 base::Passed(&hash_state))); | |
| 401 } | |
| 339 } | 402 } |
| 340 if (net_log_.IsCapturing()) { | 403 if (net_log_.IsCapturing()) { |
| 341 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, | 404 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, |
| 342 base::Bind(&FileStreamDrainedNetLogCallback, | 405 base::Bind(&FileStreamDrainedNetLogCallback, |
| 343 total_incoming_data_size, num_buffers)); | 406 total_incoming_data_size, num_buffers)); |
| 344 } | 407 } |
| 345 } | 408 } |
| 346 | 409 |
| 410 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { | |
| 411 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 412 ByteStreamReader* stream_reader = source_stream->stream_reader(); | |
| 413 if (stream_reader) { | |
| 414 source_stream->stream_reader()->RegisterCallback( | |
| 415 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), | |
| 416 source_stream)); | |
| 417 StreamActive(source_stream); | |
| 418 } | |
| 419 } | |
| 420 | |
| 421 int64_t DownloadFileImpl::TotalBytesReceived() const { | |
| 422 if (!is_sparse_file_) | |
| 423 return file_.bytes_so_far(); | |
| 424 | |
| 425 // Accumulate all valid bytes from all streams. | |
| 426 int64_t total_received = 0; | |
| 427 for (auto& stream : source_streams_) { | |
|
qinmin
2017/02/27 18:55:29
no {} meeded
xingliu
2017/02/28 00:57:06
Done.
| |
| 428 total_received += stream.second->bytes_received(); | |
| 429 } | |
| 430 | |
| 431 return total_received; | |
| 432 } | |
| 433 | |
| 347 void DownloadFileImpl::SendUpdate() { | 434 void DownloadFileImpl::SendUpdate() { |
| 435 // TODO(xingliu): Update slice info to observer to update history db. | |
| 348 BrowserThread::PostTask( | 436 BrowserThread::PostTask( |
| 349 BrowserThread::UI, | 437 BrowserThread::UI, FROM_HERE, |
| 350 FROM_HERE, | 438 base::Bind(&DownloadDestinationObserver::DestinationUpdate, observer_, |
| 351 base::Bind(&DownloadDestinationObserver::DestinationUpdate, | 439 TotalBytesReceived(), rate_estimator_.GetCountPerSecond())); |
| 352 observer_, | 440 } |
| 353 file_.bytes_so_far(), | 441 |
| 354 rate_estimator_.GetCountPerSecond())); | 442 void DownloadFileImpl::WillWriteToDisk(size_t data_len) { |
| 443 if (!update_timer_->IsRunning()) { | |
| 444 update_timer_->Start(FROM_HERE, | |
| 445 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | |
| 446 this, &DownloadFileImpl::SendUpdate); | |
| 447 } | |
| 448 rate_estimator_.Increment(data_len); | |
| 355 } | 449 } |
| 356 | 450 |
| 357 DownloadFileImpl::RenameParameters::RenameParameters( | 451 DownloadFileImpl::RenameParameters::RenameParameters( |
| 358 RenameOption option, | 452 RenameOption option, |
| 359 const base::FilePath& new_path, | 453 const base::FilePath& new_path, |
| 360 const RenameCompletionCallback& completion_callback) | 454 const RenameCompletionCallback& completion_callback) |
| 361 : option(option), | 455 : option(option), |
| 362 new_path(new_path), | 456 new_path(new_path), |
| 363 retries_left(kMaxRenameRetries), | 457 retries_left(kMaxRenameRetries), |
| 364 completion_callback(completion_callback) {} | 458 completion_callback(completion_callback) {} |
| 365 | 459 |
| 366 DownloadFileImpl::RenameParameters::~RenameParameters() {} | 460 DownloadFileImpl::RenameParameters::~RenameParameters() {} |
| 367 | 461 |
| 368 } // namespace content | 462 } // namespace content |
| OLD | NEW |