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