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

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

Issue 2890853002: Downloads: replace BrowserThread::FILE with task scheduler. (Closed)
Patch Set: Add a missing mock expectation. Created 3 years, 6 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"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "content/browser/byte_stream.h" 16 #include "content/browser/byte_stream.h"
17 #include "content/browser/download/download_create_info.h" 17 #include "content/browser/download/download_create_info.h"
18 #include "content/browser/download/download_destination_observer.h" 18 #include "content/browser/download/download_destination_observer.h"
19 #include "content/browser/download/download_interrupt_reasons_impl.h" 19 #include "content/browser/download/download_interrupt_reasons_impl.h"
20 #include "content/browser/download/download_net_log_parameters.h" 20 #include "content/browser/download/download_net_log_parameters.h"
21 #include "content/browser/download/download_stats.h" 21 #include "content/browser/download/download_stats.h"
22 #include "content/browser/download/download_task_runner.h"
22 #include "content/browser/download/parallel_download_utils.h" 23 #include "content/browser/download/parallel_download_utils.h"
23 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
24 #include "crypto/secure_hash.h" 25 #include "crypto/secure_hash.h"
25 #include "crypto/sha2.h" 26 #include "crypto/sha2.h"
26 #include "net/base/io_buffer.h" 27 #include "net/base/io_buffer.h"
27 #include "net/log/net_log.h" 28 #include "net/log/net_log.h"
28 #include "net/log/net_log_event_type.h" 29 #include "net/log/net_log_event_type.h"
29 #include "net/log/net_log_source.h" 30 #include "net/log/net_log_source.h"
30 #include "net/log/net_log_source_type.h" 31 #include "net/log/net_log_source_type.h"
31 32
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 117
117 download_item_net_log.AddEvent( 118 download_item_net_log.AddEvent(
118 net::NetLogEventType::DOWNLOAD_FILE_CREATED, 119 net::NetLogEventType::DOWNLOAD_FILE_CREATED,
119 net_log_.source().ToEventParametersCallback()); 120 net_log_.source().ToEventParametersCallback());
120 net_log_.BeginEvent( 121 net_log_.BeginEvent(
121 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, 122 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE,
122 download_item_net_log.source().ToEventParametersCallback()); 123 download_item_net_log.source().ToEventParametersCallback());
123 } 124 }
124 125
125 DownloadFileImpl::~DownloadFileImpl() { 126 DownloadFileImpl::~DownloadFileImpl() {
126 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 127 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
128
127 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE); 129 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE);
128 } 130 }
129 131
130 void DownloadFileImpl::Initialize( 132 void DownloadFileImpl::Initialize(
131 const InitializeCallback& initialize_callback, 133 const InitializeCallback& initialize_callback,
132 const CancelRequestCallback& cancel_request_callback, 134 const CancelRequestCallback& cancel_request_callback,
133 const DownloadItem::ReceivedSlices& received_slices, 135 const DownloadItem::ReceivedSlices& received_slices,
134 bool is_parallelizable) { 136 bool is_parallelizable) {
135 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 137 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
136 138
137 update_timer_.reset(new base::RepeatingTimer()); 139 update_timer_.reset(new base::RepeatingTimer());
138 int64_t bytes_so_far = 0; 140 int64_t bytes_so_far = 0;
139 cancel_request_callback_ = cancel_request_callback; 141 cancel_request_callback_ = cancel_request_callback;
140 received_slices_ = received_slices; 142 received_slices_ = received_slices;
141 if (IsSparseFile()) { 143 if (IsSparseFile()) {
142 for (const auto& received_slice : received_slices_) { 144 for (const auto& received_slice : received_slices_) {
143 bytes_so_far += received_slice.received_bytes; 145 bytes_so_far += received_slice.received_bytes;
144 } 146 }
145 } else { 147 } else {
(...skipping 23 matching lines...) Expand all
169 171
170 // Initial pull from the straw from all source streams. 172 // Initial pull from the straw from all source streams.
171 for (auto& source_stream : source_streams_) 173 for (auto& source_stream : source_streams_)
172 RegisterAndActivateStream(source_stream.second.get()); 174 RegisterAndActivateStream(source_stream.second.get());
173 } 175 }
174 176
175 void DownloadFileImpl::AddByteStream( 177 void DownloadFileImpl::AddByteStream(
176 std::unique_ptr<ByteStreamReader> stream_reader, 178 std::unique_ptr<ByteStreamReader> stream_reader,
177 int64_t offset, 179 int64_t offset,
178 int64_t length) { 180 int64_t length) {
179 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 181 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
180 182
181 source_streams_[offset] = 183 source_streams_[offset] =
182 base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader)); 184 base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader));
183 185
184 // There are writers at different offsets now, create the received slices 186 // There are writers at different offsets now, create the received slices
185 // vector if necessary. 187 // vector if necessary.
186 if (received_slices_.empty() && TotalBytesReceived() > 0) { 188 if (received_slices_.empty() && TotalBytesReceived() > 0) {
187 size_t index = AddOrMergeReceivedSliceIntoSortedArray( 189 size_t index = AddOrMergeReceivedSliceIntoSortedArray(
188 DownloadItem::ReceivedSlice(0, TotalBytesReceived()), received_slices_); 190 DownloadItem::ReceivedSlice(0, TotalBytesReceived()), received_slices_);
189 DCHECK_EQ(index, 0u); 191 DCHECK_EQ(index, 0u);
190 } 192 }
191 // If the file is initialized, start to write data, or wait until file opened. 193 // If the file is initialized, start to write data, or wait until file opened.
192 if (file_.in_progress()) 194 if (file_.in_progress())
193 RegisterAndActivateStream(source_streams_[offset].get()); 195 RegisterAndActivateStream(source_streams_[offset].get());
194 } 196 }
195 197
196 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, 198 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset,
197 const char* data, 199 const char* data,
198 size_t data_len) { 200 size_t data_len) {
199 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 201 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
202
200 WillWriteToDisk(data_len); 203 WillWriteToDisk(data_len);
201 return file_.WriteDataToFile(offset, data, data_len); 204 return file_.WriteDataToFile(offset, data, data_len);
202 } 205 }
203 206
204 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, 207 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream,
205 size_t bytes_available_to_write, 208 size_t bytes_available_to_write,
206 size_t* bytes_to_write) { 209 size_t* bytes_to_write) {
207 if (source_stream->length() == kNoBytesToWrite) { 210 if (source_stream->length() == kNoBytesToWrite) {
208 *bytes_to_write = 0; 211 *bytes_to_write = 0;
209 return true; 212 return true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) * 270 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) *
268 (1 << attempt_number); 271 (1 << attempt_number);
269 } 272 }
270 273
271 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { 274 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) {
272 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; 275 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
273 } 276 }
274 277
275 void DownloadFileImpl::RenameWithRetryInternal( 278 void DownloadFileImpl::RenameWithRetryInternal(
276 std::unique_ptr<RenameParameters> parameters) { 279 std::unique_ptr<RenameParameters> parameters) {
277 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 280 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
278 281
279 base::FilePath new_path = parameters->new_path; 282 base::FilePath new_path = parameters->new_path;
280 283
281 if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) { 284 if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) {
282 int uniquifier = 285 int uniquifier =
283 base::GetUniquePathNumber(new_path, base::FilePath::StringType()); 286 base::GetUniquePathNumber(new_path, base::FilePath::StringType());
284 if (uniquifier > 0) 287 if (uniquifier > 0)
285 new_path = new_path.InsertBeforeExtensionASCII( 288 new_path = new_path.InsertBeforeExtensionASCII(
286 base::StringPrintf(" (%d)", uniquifier)); 289 base::StringPrintf(" (%d)", uniquifier));
287 } 290 }
288 291
289 DownloadInterruptReason reason = file_.Rename(new_path); 292 DownloadInterruptReason reason = file_.Rename(new_path);
290 293
291 // Attempt to retry the rename if possible. If the rename failed and the 294 // Attempt to retry the rename if possible. If the rename failed and the
292 // subsequent open also failed, then in_progress() would be false. We don't 295 // subsequent open also failed, then in_progress() would be false. We don't
293 // try to retry renames if the in_progress() was false to begin with since we 296 // try to retry renames if the in_progress() was false to begin with since we
294 // have less assurance that the file at file_.full_path() was the one we were 297 // have less assurance that the file at file_.full_path() was the one we were
295 // working with. 298 // working with.
296 if (ShouldRetryFailedRename(reason) && file_.in_progress() && 299 if (ShouldRetryFailedRename(reason) && file_.in_progress() &&
297 parameters->retries_left > 0) { 300 parameters->retries_left > 0) {
298 int attempt_number = kMaxRenameRetries - parameters->retries_left; 301 int attempt_number = kMaxRenameRetries - parameters->retries_left;
299 --parameters->retries_left; 302 --parameters->retries_left;
300 if (parameters->time_of_first_failure.is_null()) 303 if (parameters->time_of_first_failure.is_null())
301 parameters->time_of_first_failure = base::TimeTicks::Now(); 304 parameters->time_of_first_failure = base::TimeTicks::Now();
302 BrowserThread::PostDelayedTask( 305 GetDownloadTaskRunner()->PostDelayedTask(
303 BrowserThread::FILE,
304 FROM_HERE, 306 FROM_HERE,
305 base::Bind(&DownloadFileImpl::RenameWithRetryInternal, 307 base::Bind(&DownloadFileImpl::RenameWithRetryInternal,
306 weak_factory_.GetWeakPtr(), 308 weak_factory_.GetWeakPtr(),
307 base::Passed(std::move(parameters))), 309 base::Passed(std::move(parameters))),
308 GetRetryDelayForFailedRename(attempt_number)); 310 GetRetryDelayForFailedRename(attempt_number));
309 return; 311 return;
310 } 312 }
311 313
312 if (!parameters->time_of_first_failure.is_null()) 314 if (!parameters->time_of_first_failure.is_null())
313 RecordDownloadFileRenameResultAfterRetry( 315 RecordDownloadFileRenameResultAfterRetry(
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 break; 463 break;
462 } 464 }
463 now = base::TimeTicks::Now(); 465 now = base::TimeTicks::Now();
464 } while (state == ByteStreamReader::STREAM_HAS_DATA && 466 } while (state == ByteStreamReader::STREAM_HAS_DATA &&
465 reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta && 467 reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta &&
466 !should_terminate); 468 !should_terminate);
467 469
468 // If we're stopping to yield the thread, post a task so we come back. 470 // If we're stopping to yield the thread, post a task so we come back.
469 if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta && 471 if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta &&
470 !should_terminate) { 472 !should_terminate) {
471 BrowserThread::PostTask( 473 GetDownloadTaskRunner()->PostTask(
472 BrowserThread::FILE, FROM_HERE, 474 FROM_HERE, base::Bind(&DownloadFileImpl::StreamActive,
473 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), 475 weak_factory_.GetWeakPtr(), source_stream));
474 source_stream));
475 } 476 }
476 477
477 if (total_incoming_data_size) 478 if (total_incoming_data_size)
478 RecordFileThreadReceiveBuffers(num_buffers); 479 RecordFileThreadReceiveBuffers(num_buffers);
479 480
480 RecordContiguousWriteTime(now - start); 481 RecordContiguousWriteTime(now - start);
481 482
482 // Take care of communication with our observer. 483 // Take care of communication with our observer.
483 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 484 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
484 HandleStreamError(source_stream, reason); 485 HandleStreamError(source_stream, reason);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 } 520 }
520 } 521 }
521 if (net_log_.IsCapturing()) { 522 if (net_log_.IsCapturing()) {
522 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, 523 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED,
523 base::Bind(&FileStreamDrainedNetLogCallback, 524 base::Bind(&FileStreamDrainedNetLogCallback,
524 total_incoming_data_size, num_buffers)); 525 total_incoming_data_size, num_buffers));
525 } 526 }
526 } 527 }
527 528
528 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { 529 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) {
529 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 530 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
531
530 ByteStreamReader* stream_reader = source_stream->stream_reader(); 532 ByteStreamReader* stream_reader = source_stream->stream_reader();
531 if (stream_reader) { 533 if (stream_reader) {
532 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive, 534 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive,
533 weak_factory_.GetWeakPtr(), 535 weak_factory_.GetWeakPtr(),
534 source_stream)); 536 source_stream));
535 // Truncate |source_stream|'s length if necessary. 537 // Truncate |source_stream|'s length if necessary.
536 for (const auto& received_slice : received_slices_) { 538 for (const auto& received_slice : received_slices_) {
537 source_stream->TruncateLengthWithWrittenDataBlock( 539 source_stream->TruncateLengthWithWrittenDataBlock(
538 received_slice.offset, received_slice.received_bytes); 540 received_slice.offset, received_slice.received_bytes);
539 } 541 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 if (slices_to_download.size() > 1) { 611 if (slices_to_download.size() > 1) {
610 // If there are 1 or more holes in the file, download is not finished. 612 // If there are 1 or more holes in the file, download is not finished.
611 // Some streams might not have been added to |source_streams_| yet. 613 // Some streams might not have been added to |source_streams_| yet.
612 return false; 614 return false;
613 } 615 }
614 return TotalBytesReceived() == potential_file_length_; 616 return TotalBytesReceived() == potential_file_length_;
615 } 617 }
616 618
617 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, 619 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
618 DownloadInterruptReason reason) { 620 DownloadInterruptReason reason) {
619 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 621 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
622
620 source_stream->stream_reader()->RegisterCallback(base::Closure()); 623 source_stream->stream_reader()->RegisterCallback(base::Closure());
621 source_stream->set_finished(true); 624 source_stream->set_finished(true);
622 num_active_streams_--; 625 num_active_streams_--;
623 626
624 bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite); 627 bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite);
625 628
626 if (IsSparseFile() && !can_recover_from_error) { 629 if (IsSparseFile() && !can_recover_from_error) {
627 // If a neighboring stream request is available, check if it can help 630 // If a neighboring stream request is available, check if it can help
628 // download all the data left by |source stream| or has already done so. We 631 // download all the data left by |source stream| or has already done so. We
629 // want to avoid the situation that a server always fail additional requests 632 // want to avoid the situation that a server always fail additional requests
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 const base::FilePath& new_path, 729 const base::FilePath& new_path,
727 const RenameCompletionCallback& completion_callback) 730 const RenameCompletionCallback& completion_callback)
728 : option(option), 731 : option(option),
729 new_path(new_path), 732 new_path(new_path),
730 retries_left(kMaxRenameRetries), 733 retries_left(kMaxRenameRetries),
731 completion_callback(completion_callback) {} 734 completion_callback(completion_callback) {}
732 735
733 DownloadFileImpl::RenameParameters::~RenameParameters() {} 736 DownloadFileImpl::RenameParameters::~RenameParameters() {}
734 737
735 } // namespace content 738 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698