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, int64_t length) | |
| 45 : offset_(offset), length_(length), bytes_written_(0), finished_(false) {} | |
|
asanka
2017/03/02 19:37:43
Is this 'git cl format's doing?
xingliu
2017/03/02 23:06:14
Yes, I think so.
| |
| 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] = | |
| 76 base::MakeUnique<SourceStream>(save_info_->offset, 0); | |
| 77 DCHECK(source_streams_.size() == static_cast<size_t>(1)); | |
| 78 source_streams_.begin()->second->SetByteStream(std::move(stream_reader)); | |
|
David Trainor- moved to gerrit
2017/03/02 18:24:50
source_streams_[save_info_->offset]->SetByteStream
xingliu
2017/03/02 19:21:20
Done.
| |
| 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 |
| 122 void DownloadFileImpl::AddByteStream( | |
| 123 std::unique_ptr<ByteStreamReader> stream_reader, | |
| 124 int64_t offset) { | |
| 125 // |source_streams_| is not thread safe, must be modified on the same thread. | |
|
asanka
2017/03/02 19:37:43
This is not safe.
The problem here is that the Do
xingliu
2017/03/02 23:06:14
Done,
Thanks for this suggestion. Yeah, good catc
| |
| 126 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 127 | |
| 128 // The |source_streams_| must have an existing entry for the stream reader. | |
| 129 auto current_source_stream = source_streams_.find(offset); | |
| 130 DCHECK(current_source_stream != source_streams_.end()); | |
| 131 SourceStream* stream = current_source_stream->second.get(); | |
| 132 stream->SetByteStream(std::move(stream_reader)); | |
| 133 | |
| 134 // Start to pull data from the stream. | |
| 135 BrowserThread::PostTask( | |
| 136 BrowserThread::FILE, FROM_HERE, | |
| 137 base::Bind(&DownloadFileImpl::RegisterAndActivateStream, | |
| 138 weak_factory_.GetWeakPtr(), stream)); | |
| 139 } | |
| 140 | |
| 106 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( | 141 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( |
| 107 const char* data, size_t data_len) { | 142 const char* data, size_t data_len) { |
| 108 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 143 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 144 WillWriteToDisk(data_len); | |
| 145 return file_.AppendDataToFile(data, data_len); | |
| 146 } | |
| 109 | 147 |
| 110 if (!update_timer_->IsRunning()) { | 148 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, |
| 111 update_timer_->Start(FROM_HERE, | 149 const char* data, |
| 112 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 150 size_t data_len) { |
| 113 this, &DownloadFileImpl::SendUpdate); | 151 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 114 } | 152 WillWriteToDisk(data_len); |
| 115 rate_estimator_.Increment(data_len); | 153 return file_.WriteDataToFile(offset, data, data_len); |
| 116 return file_.AppendDataToFile(data, data_len); | |
| 117 } | 154 } |
| 118 | 155 |
| 119 void DownloadFileImpl::RenameAndUniquify( | 156 void DownloadFileImpl::RenameAndUniquify( |
| 120 const base::FilePath& full_path, | 157 const base::FilePath& full_path, |
| 121 const RenameCompletionCallback& callback) { | 158 const RenameCompletionCallback& callback) { |
| 122 std::unique_ptr<RenameParameters> parameters( | 159 std::unique_ptr<RenameParameters> parameters( |
| 123 new RenameParameters(UNIQUIFY, full_path, callback)); | 160 new RenameParameters(UNIQUIFY, full_path, callback)); |
| 124 RenameWithRetryInternal(std::move(parameters)); | 161 RenameWithRetryInternal(std::move(parameters)); |
| 125 } | 162 } |
| 126 | 163 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 parameters->source_url, | 243 parameters->source_url, |
| 207 parameters->referrer_url); | 244 parameters->referrer_url); |
| 208 } | 245 } |
| 209 | 246 |
| 210 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 247 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 211 // Make sure our information is updated, since we're about to | 248 // Make sure our information is updated, since we're about to |
| 212 // error out. | 249 // error out. |
| 213 SendUpdate(); | 250 SendUpdate(); |
| 214 | 251 |
| 215 // Null out callback so that we don't do any more stream processing. | 252 // Null out callback so that we don't do any more stream processing. |
| 216 stream_reader_->RegisterCallback(base::Closure()); | 253 for (auto& stream : source_streams_) { |
| 254 ByteStreamReader* stream_reader = stream.second->stream_reader(); | |
| 255 if (stream_reader) | |
| 256 stream_reader->RegisterCallback(base::Closure()); | |
| 257 } | |
| 217 | 258 |
| 218 new_path.clear(); | 259 new_path.clear(); |
| 219 } | 260 } |
| 220 | 261 |
| 221 BrowserThread::PostTask( | 262 BrowserThread::PostTask( |
| 222 BrowserThread::UI, | 263 BrowserThread::UI, |
| 223 FROM_HERE, | 264 FROM_HERE, |
| 224 base::Bind(parameters->completion_callback, reason, new_path)); | 265 base::Bind(parameters->completion_callback, reason, new_path)); |
| 225 } | 266 } |
| 226 | 267 |
| 227 void DownloadFileImpl::Detach() { | 268 void DownloadFileImpl::Detach() { |
| 228 file_.Detach(); | 269 file_.Detach(); |
| 229 } | 270 } |
| 230 | 271 |
| 231 void DownloadFileImpl::Cancel() { | 272 void DownloadFileImpl::Cancel() { |
| 232 file_.Cancel(); | 273 file_.Cancel(); |
| 233 } | 274 } |
| 234 | 275 |
| 235 const base::FilePath& DownloadFileImpl::FullPath() const { | 276 const base::FilePath& DownloadFileImpl::FullPath() const { |
| 236 return file_.full_path(); | 277 return file_.full_path(); |
| 237 } | 278 } |
| 238 | 279 |
| 239 bool DownloadFileImpl::InProgress() const { | 280 bool DownloadFileImpl::InProgress() const { |
| 240 return file_.in_progress(); | 281 return file_.in_progress(); |
| 241 } | 282 } |
| 242 | 283 |
| 243 void DownloadFileImpl::StreamActive() { | 284 void DownloadFileImpl::StreamActive(SourceStream* source_stream) { |
| 285 DCHECK(source_stream->stream_reader()); | |
| 244 base::TimeTicks start(base::TimeTicks::Now()); | 286 base::TimeTicks start(base::TimeTicks::Now()); |
| 245 base::TimeTicks now; | 287 base::TimeTicks now; |
| 246 scoped_refptr<net::IOBuffer> incoming_data; | 288 scoped_refptr<net::IOBuffer> incoming_data; |
| 247 size_t incoming_data_size = 0; | 289 size_t incoming_data_size = 0; |
| 248 size_t total_incoming_data_size = 0; | 290 size_t total_incoming_data_size = 0; |
| 249 size_t num_buffers = 0; | 291 size_t num_buffers = 0; |
| 292 bool should_terminate = false; | |
| 250 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); | 293 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); |
| 251 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; | 294 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 252 base::TimeDelta delta( | 295 base::TimeDelta delta( |
| 253 base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs)); | 296 base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs)); |
| 254 | 297 |
| 255 // Take care of any file local activity required. | 298 // Take care of any file local activity required. |
| 256 do { | 299 do { |
| 257 state = stream_reader_->Read(&incoming_data, &incoming_data_size); | 300 state = source_stream->stream_reader()->Read(&incoming_data, |
| 301 &incoming_data_size); | |
| 258 | 302 |
| 259 switch (state) { | 303 switch (state) { |
| 260 case ByteStreamReader::STREAM_EMPTY: | 304 case ByteStreamReader::STREAM_EMPTY: |
| 261 break; | 305 break; |
| 262 case ByteStreamReader::STREAM_HAS_DATA: | 306 case ByteStreamReader::STREAM_HAS_DATA: |
| 263 { | 307 { |
| 264 ++num_buffers; | 308 ++num_buffers; |
| 265 base::TimeTicks write_start(base::TimeTicks::Now()); | 309 base::TimeTicks write_start(base::TimeTicks::Now()); |
| 266 reason = AppendDataToFile( | 310 // Stop the stream if it writes more bytes than expected. |
| 267 incoming_data.get()->data(), incoming_data_size); | 311 if (source_stream->length() > 0 && |
| 312 source_stream->bytes_written() + | |
| 313 static_cast<int64_t>(incoming_data_size) >= | |
| 314 source_stream->length()) { | |
| 315 should_terminate = true; | |
| 316 incoming_data_size = | |
| 317 source_stream->length() - source_stream->bytes_written(); | |
| 318 } | |
| 319 | |
| 320 if (is_sparse_file_) { | |
| 321 reason = WriteDataToFile( | |
| 322 source_stream->offset() + source_stream->bytes_written(), | |
| 323 incoming_data.get()->data(), incoming_data_size); | |
| 324 } else { | |
| 325 reason = AppendDataToFile(incoming_data.get()->data(), | |
|
asanka
2017/03/02 19:37:43
I'm assuming that the plan is to get rid of this l
xingliu
2017/03/02 23:06:14
Done.
| |
| 326 incoming_data_size); | |
| 327 } | |
| 268 disk_writes_time_ += (base::TimeTicks::Now() - write_start); | 328 disk_writes_time_ += (base::TimeTicks::Now() - write_start); |
| 269 bytes_seen_ += incoming_data_size; | 329 bytes_seen_ += incoming_data_size; |
| 270 total_incoming_data_size += incoming_data_size; | 330 total_incoming_data_size += incoming_data_size; |
| 331 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) | |
| 332 source_stream->OnWriteBytesToDisk(incoming_data_size); | |
| 271 } | 333 } |
| 272 break; | 334 break; |
| 273 case ByteStreamReader::STREAM_COMPLETE: | 335 case ByteStreamReader::STREAM_COMPLETE: |
| 274 { | 336 { |
| 275 reason = static_cast<DownloadInterruptReason>( | 337 reason = static_cast<DownloadInterruptReason>( |
| 276 stream_reader_->GetStatus()); | 338 source_stream->stream_reader()->GetStatus()); |
| 277 SendUpdate(); | 339 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 } | 340 } |
| 285 break; | 341 break; |
| 286 default: | 342 default: |
| 287 NOTREACHED(); | 343 NOTREACHED(); |
| 288 break; | 344 break; |
| 289 } | 345 } |
| 290 now = base::TimeTicks::Now(); | 346 now = base::TimeTicks::Now(); |
| 291 } while (state == ByteStreamReader::STREAM_HAS_DATA && | 347 } while (state == ByteStreamReader::STREAM_HAS_DATA && |
| 292 reason == DOWNLOAD_INTERRUPT_REASON_NONE && | 348 reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta && |
| 293 now - start <= delta); | 349 !should_terminate); |
| 294 | 350 |
| 295 // If we're stopping to yield the thread, post a task so we come back. | 351 // If we're stopping to yield the thread, post a task so we come back. |
| 296 if (state == ByteStreamReader::STREAM_HAS_DATA && | 352 if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta && |
| 297 now - start > delta) { | 353 !should_terminate) { |
| 298 BrowserThread::PostTask( | 354 BrowserThread::PostTask( |
| 299 BrowserThread::FILE, FROM_HERE, | 355 BrowserThread::FILE, FROM_HERE, |
| 300 base::Bind(&DownloadFileImpl::StreamActive, | 356 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), |
| 301 weak_factory_.GetWeakPtr())); | 357 source_stream)); |
| 302 } | 358 } |
| 303 | 359 |
| 304 if (total_incoming_data_size) | 360 if (total_incoming_data_size) |
| 305 RecordFileThreadReceiveBuffers(num_buffers); | 361 RecordFileThreadReceiveBuffers(num_buffers); |
| 306 | 362 |
| 307 RecordContiguousWriteTime(now - start); | 363 RecordContiguousWriteTime(now - start); |
| 308 | 364 |
| 309 // Take care of communication with our observer. | 365 // Take care of communication with our observer. |
| 310 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 366 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 311 // Error case for both upstream source and file write. | 367 // Error case for both upstream source and file write. |
| 312 // Shut down processing and signal an error to our observer. | 368 // Shut down processing and signal an error to our observer. |
| 313 // Our observer will clean us up. | 369 // Our observer will clean us up. |
| 314 stream_reader_->RegisterCallback(base::Closure()); | 370 source_stream->stream_reader()->RegisterCallback(base::Closure()); |
| 315 weak_factory_.InvalidateWeakPtrs(); | 371 weak_factory_.InvalidateWeakPtrs(); |
| 316 SendUpdate(); // Make info up to date before error. | 372 SendUpdate(); // Make info up to date before error. |
| 317 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | 373 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); |
| 318 BrowserThread::PostTask( | 374 BrowserThread::PostTask( |
| 319 BrowserThread::UI, | 375 BrowserThread::UI, FROM_HERE, |
| 320 FROM_HERE, | 376 base::Bind(&DownloadDestinationObserver::DestinationError, observer_, |
| 321 base::Bind(&DownloadDestinationObserver::DestinationError, | 377 reason, TotalBytesReceived(), base::Passed(&hash_state))); |
| 322 observer_, | 378 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { |
| 323 reason, | 379 // Signal successful completion or termination of the current stream. |
| 324 file_.bytes_so_far(), | 380 source_stream->stream_reader()->RegisterCallback(base::Closure()); |
| 325 base::Passed(&hash_state))); | 381 source_stream->set_finished(true); |
| 326 } else if (state == ByteStreamReader::STREAM_COMPLETE) { | 382 |
| 327 // Signal successful completion and shut down processing. | 383 // Inform observers. |
| 328 stream_reader_->RegisterCallback(base::Closure()); | |
| 329 weak_factory_.InvalidateWeakPtrs(); | |
| 330 SendUpdate(); | 384 SendUpdate(); |
| 331 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | 385 |
| 332 BrowserThread::PostTask( | 386 bool all_stream_complete = true; |
| 333 BrowserThread::UI, | 387 for (auto& stream : source_streams_) { |
| 334 FROM_HERE, | 388 if (!stream.second->is_finished()) { |
| 335 base::Bind(&DownloadDestinationObserver::DestinationCompleted, | 389 all_stream_complete = false; |
|
asanka
2017/03/02 19:37:43
This kind of logic tends to be quite fragile. Imag
xingliu
2017/03/02 23:06:14
Done, Added some comment in the header.
Already n
| |
| 336 observer_, | 390 break; |
| 337 file_.bytes_so_far(), | 391 } |
| 338 base::Passed(&hash_state))); | 392 } |
| 393 | |
| 394 // All the stream reader are completed, shut down file IO processing. | |
| 395 if (all_stream_complete) { | |
| 396 RecordFileBandwidth(bytes_seen_, disk_writes_time_, | |
| 397 base::TimeTicks::Now() - download_start_); | |
| 398 weak_factory_.InvalidateWeakPtrs(); | |
| 399 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); | |
| 400 update_timer_.reset(); | |
| 401 BrowserThread::PostTask( | |
| 402 BrowserThread::UI, FROM_HERE, | |
| 403 base::Bind(&DownloadDestinationObserver::DestinationCompleted, | |
| 404 observer_, TotalBytesReceived(), | |
| 405 base::Passed(&hash_state))); | |
| 406 } | |
| 339 } | 407 } |
| 340 if (net_log_.IsCapturing()) { | 408 if (net_log_.IsCapturing()) { |
| 341 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, | 409 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, |
| 342 base::Bind(&FileStreamDrainedNetLogCallback, | 410 base::Bind(&FileStreamDrainedNetLogCallback, |
| 343 total_incoming_data_size, num_buffers)); | 411 total_incoming_data_size, num_buffers)); |
| 344 } | 412 } |
| 345 } | 413 } |
| 346 | 414 |
| 415 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { | |
| 416 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 417 ByteStreamReader* stream_reader = source_stream->stream_reader(); | |
| 418 if (stream_reader) { | |
| 419 stream_reader->RegisterCallback( | |
| 420 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), | |
| 421 source_stream)); | |
| 422 StreamActive(source_stream); | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 int64_t DownloadFileImpl::TotalBytesReceived() const { | |
| 427 // TODO(xingliu): Use slice info to figure out total bytes received. | |
| 428 return file_.bytes_so_far(); | |
| 429 } | |
| 430 | |
| 347 void DownloadFileImpl::SendUpdate() { | 431 void DownloadFileImpl::SendUpdate() { |
| 432 // TODO(xingliu): Update slice info to observer to update history db. | |
| 348 BrowserThread::PostTask( | 433 BrowserThread::PostTask( |
| 349 BrowserThread::UI, | 434 BrowserThread::UI, FROM_HERE, |
| 350 FROM_HERE, | 435 base::Bind(&DownloadDestinationObserver::DestinationUpdate, observer_, |
| 351 base::Bind(&DownloadDestinationObserver::DestinationUpdate, | 436 TotalBytesReceived(), rate_estimator_.GetCountPerSecond())); |
| 352 observer_, | 437 } |
| 353 file_.bytes_so_far(), | 438 |
| 354 rate_estimator_.GetCountPerSecond())); | 439 void DownloadFileImpl::WillWriteToDisk(size_t data_len) { |
| 440 if (!update_timer_->IsRunning()) { | |
| 441 update_timer_->Start(FROM_HERE, | |
| 442 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | |
| 443 this, &DownloadFileImpl::SendUpdate); | |
| 444 } | |
| 445 rate_estimator_.Increment(data_len); | |
| 355 } | 446 } |
| 356 | 447 |
| 357 DownloadFileImpl::RenameParameters::RenameParameters( | 448 DownloadFileImpl::RenameParameters::RenameParameters( |
| 358 RenameOption option, | 449 RenameOption option, |
| 359 const base::FilePath& new_path, | 450 const base::FilePath& new_path, |
| 360 const RenameCompletionCallback& completion_callback) | 451 const RenameCompletionCallback& completion_callback) |
| 361 : option(option), | 452 : option(option), |
| 362 new_path(new_path), | 453 new_path(new_path), |
| 363 retries_left(kMaxRenameRetries), | 454 retries_left(kMaxRenameRetries), |
| 364 completion_callback(completion_callback) {} | 455 completion_callback(completion_callback) {} |
| 365 | 456 |
| 366 DownloadFileImpl::RenameParameters::~RenameParameters() {} | 457 DownloadFileImpl::RenameParameters::~RenameParameters() {} |
| 367 | 458 |
| 368 } // namespace content | 459 } // namespace content |
| OLD | NEW |