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

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

Issue 2712713007: Make DownloadFileImpl handle multiple byte streams. (Closed)
Patch Set: Export the new class for linking on windows. Created 3 years, 10 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/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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698