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/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "content/browser/byte_stream.h" | 15 #include "content/browser/byte_stream.h" |
16 #include "content/browser/download/download_create_info.h" | 16 #include "content/browser/download/download_create_info.h" |
| 17 #include "content/browser/download/download_destination_observer.h" |
17 #include "content/browser/download/download_interrupt_reasons_impl.h" | 18 #include "content/browser/download/download_interrupt_reasons_impl.h" |
18 #include "content/browser/download/download_net_log_parameters.h" | 19 #include "content/browser/download/download_net_log_parameters.h" |
19 #include "content/browser/download/download_stats.h" | 20 #include "content/browser/download/download_stats.h" |
20 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/download_destination_observer.h" | 22 #include "crypto/secure_hash.h" |
| 23 #include "crypto/sha2.h" |
22 #include "net/base/io_buffer.h" | 24 #include "net/base/io_buffer.h" |
23 | 25 |
24 namespace content { | 26 namespace content { |
25 | 27 |
26 const int kUpdatePeriodMs = 500; | 28 const int kUpdatePeriodMs = 500; |
27 const int kMaxTimeBlockingFileThreadMs = 1000; | 29 const int kMaxTimeBlockingFileThreadMs = 1000; |
28 | 30 |
29 // These constants control the default retry behavior for failing renames. Each | 31 // These constants control the default retry behavior for failing renames. Each |
30 // retry is performed after a delay that is twice the previous delay. The | 32 // retry is performed after a delay that is twice the previous delay. The |
31 // initial delay is specified by kInitialRenameRetryDelayMs. | 33 // initial delay is specified by kInitialRenameRetryDelayMs. |
32 const int kMaxRenameRetries = 3; | |
33 const int kInitialRenameRetryDelayMs = 200; | 34 const int kInitialRenameRetryDelayMs = 200; |
34 | 35 |
35 int DownloadFile::number_active_objects_ = 0; | 36 // Number of times a failing rename is retried before giving up. |
| 37 const int kMaxRenameRetries = 3; |
36 | 38 |
37 DownloadFileImpl::DownloadFileImpl( | 39 DownloadFileImpl::DownloadFileImpl( |
38 const DownloadSaveInfo& save_info, | 40 scoped_ptr<DownloadSaveInfo> save_info, |
39 const base::FilePath& default_download_directory, | 41 const base::FilePath& default_download_directory, |
40 const GURL& url, | |
41 const GURL& referrer_url, | |
42 bool calculate_hash, | |
43 base::File file, | |
44 scoped_ptr<ByteStreamReader> stream, | 42 scoped_ptr<ByteStreamReader> stream, |
45 const net::BoundNetLog& bound_net_log, | 43 const net::BoundNetLog& bound_net_log, |
46 base::WeakPtr<DownloadDestinationObserver> observer) | 44 base::WeakPtr<DownloadDestinationObserver> observer) |
47 : file_(save_info.file_path, | 45 : file_(bound_net_log), |
48 url, | 46 save_info_(std::move(save_info)), |
49 referrer_url, | |
50 save_info.offset, | |
51 calculate_hash, | |
52 save_info.hash_state, | |
53 std::move(file), | |
54 bound_net_log), | |
55 default_download_directory_(default_download_directory), | 47 default_download_directory_(default_download_directory), |
56 stream_reader_(std::move(stream)), | 48 stream_reader_(std::move(stream)), |
57 bytes_seen_(0), | 49 bytes_seen_(0), |
58 bound_net_log_(bound_net_log), | 50 bound_net_log_(bound_net_log), |
59 observer_(observer), | 51 observer_(observer), |
60 weak_factory_(this) {} | 52 weak_factory_(this) {} |
61 | 53 |
62 DownloadFileImpl::~DownloadFileImpl() { | 54 DownloadFileImpl::~DownloadFileImpl() { |
63 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 55 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
64 --number_active_objects_; | |
65 } | 56 } |
66 | 57 |
67 void DownloadFileImpl::Initialize(const InitializeCallback& callback) { | 58 void DownloadFileImpl::Initialize(const InitializeCallback& callback) { |
68 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 59 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
69 | 60 |
70 update_timer_.reset(new base::RepeatingTimer()); | 61 update_timer_.reset(new base::RepeatingTimer()); |
71 DownloadInterruptReason result = | 62 DownloadInterruptReason result = file_.Initialize( |
72 file_.Initialize(default_download_directory_); | 63 save_info_->file_path, default_download_directory_, |
| 64 std::move(save_info_->file), save_info_->offset, save_info_->prefix_hash, |
| 65 std::move(save_info_->hash_state)); |
73 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { | 66 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
74 BrowserThread::PostTask( | 67 BrowserThread::PostTask( |
75 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); | 68 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); |
76 return; | 69 return; |
77 } | 70 } |
78 | 71 |
79 stream_reader_->RegisterCallback( | 72 stream_reader_->RegisterCallback( |
80 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr())); | 73 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr())); |
81 | 74 |
82 download_start_ = base::TimeTicks::Now(); | 75 download_start_ = base::TimeTicks::Now(); |
83 | 76 |
84 // Primarily to make reset to zero in restart visible to owner. | 77 // Primarily to make reset to zero in restart visible to owner. |
85 SendUpdate(); | 78 SendUpdate(); |
86 | 79 |
87 // Initial pull from the straw. | 80 // Initial pull from the straw. |
88 StreamActive(); | 81 StreamActive(); |
89 | 82 |
90 BrowserThread::PostTask( | 83 BrowserThread::PostTask( |
91 BrowserThread::UI, FROM_HERE, base::Bind( | 84 BrowserThread::UI, FROM_HERE, base::Bind( |
92 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); | 85 callback, DOWNLOAD_INTERRUPT_REASON_NONE)); |
93 | |
94 ++number_active_objects_; | |
95 } | 86 } |
96 | 87 |
97 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( | 88 DownloadInterruptReason DownloadFileImpl::AppendDataToFile( |
98 const char* data, size_t data_len) { | 89 const char* data, size_t data_len) { |
99 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
100 | 91 |
101 if (!update_timer_->IsRunning()) { | 92 if (!update_timer_->IsRunning()) { |
102 update_timer_->Start(FROM_HERE, | 93 update_timer_->Start(FROM_HERE, |
103 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 94 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
104 this, &DownloadFileImpl::SendUpdate); | 95 this, &DownloadFileImpl::SendUpdate); |
105 } | 96 } |
106 rate_estimator_.Increment(data_len); | 97 rate_estimator_.Increment(data_len); |
107 return file_.AppendDataToFile(data, data_len); | 98 return file_.AppendDataToFile(data, data_len); |
108 } | 99 } |
109 | 100 |
110 void DownloadFileImpl::RenameAndUniquify( | 101 void DownloadFileImpl::RenameAndUniquify( |
111 const base::FilePath& full_path, | 102 const base::FilePath& full_path, |
112 const RenameCompletionCallback& callback) { | 103 const RenameCompletionCallback& callback) { |
113 RenameWithRetryInternal( | 104 scoped_ptr<RenameParameters> parameters( |
114 full_path, UNIQUIFY, kMaxRenameRetries, base::TimeTicks(), callback); | 105 new RenameParameters(UNIQUIFY, full_path, callback)); |
| 106 RenameWithRetryInternal(std::move(parameters)); |
115 } | 107 } |
116 | 108 |
117 void DownloadFileImpl::RenameAndAnnotate( | 109 void DownloadFileImpl::RenameAndAnnotate( |
118 const base::FilePath& full_path, | 110 const base::FilePath& full_path, |
| 111 const std::string& client_guid, |
| 112 const GURL& source_url, |
| 113 const GURL& referrer_url, |
119 const RenameCompletionCallback& callback) { | 114 const RenameCompletionCallback& callback) { |
120 RenameWithRetryInternal(full_path, | 115 scoped_ptr<RenameParameters> parameters(new RenameParameters( |
121 ANNOTATE_WITH_SOURCE_INFORMATION, | 116 ANNOTATE_WITH_SOURCE_INFORMATION, full_path, callback)); |
122 kMaxRenameRetries, | 117 parameters->client_guid = client_guid; |
123 base::TimeTicks(), | 118 parameters->source_url = source_url; |
124 callback); | 119 parameters->referrer_url = referrer_url; |
| 120 RenameWithRetryInternal(std::move(parameters)); |
125 } | 121 } |
126 | 122 |
127 base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename( | 123 base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename( |
128 int attempt_number) { | 124 int attempt_number) { |
129 DCHECK_GE(attempt_number, 0); | 125 DCHECK_GE(attempt_number, 0); |
130 // |delay| starts at kInitialRenameRetryDelayMs and increases by a factor of | 126 // |delay| starts at kInitialRenameRetryDelayMs and increases by a factor of |
131 // 2 at each subsequent retry. Assumes that |retries_left| starts at | 127 // 2 at each subsequent retry. Assumes that |retries_left| starts at |
132 // kMaxRenameRetries. Also assumes that kMaxRenameRetries is less than the | 128 // kMaxRenameRetries. Also assumes that kMaxRenameRetries is less than the |
133 // number of bits in an int. | 129 // number of bits in an int. |
134 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) * | 130 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) * |
135 (1 << attempt_number); | 131 (1 << attempt_number); |
136 } | 132 } |
137 | 133 |
138 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { | 134 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { |
139 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; | 135 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; |
140 } | 136 } |
141 | 137 |
142 void DownloadFileImpl::RenameWithRetryInternal( | 138 void DownloadFileImpl::RenameWithRetryInternal( |
143 const base::FilePath& full_path, | 139 scoped_ptr<RenameParameters> parameters) { |
144 RenameOption option, | |
145 int retries_left, | |
146 base::TimeTicks time_of_first_failure, | |
147 const RenameCompletionCallback& callback) { | |
148 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 140 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
149 | 141 |
150 base::FilePath new_path(full_path); | 142 base::FilePath new_path = parameters->new_path; |
151 | 143 |
152 if ((option & UNIQUIFY) && full_path != file_.full_path()) { | 144 if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) { |
153 int uniquifier = | 145 int uniquifier = |
154 base::GetUniquePathNumber(new_path, base::FilePath::StringType()); | 146 base::GetUniquePathNumber(new_path, base::FilePath::StringType()); |
155 if (uniquifier > 0) | 147 if (uniquifier > 0) |
156 new_path = new_path.InsertBeforeExtensionASCII( | 148 new_path = new_path.InsertBeforeExtensionASCII( |
157 base::StringPrintf(" (%d)", uniquifier)); | 149 base::StringPrintf(" (%d)", uniquifier)); |
158 } | 150 } |
159 | 151 |
160 DownloadInterruptReason reason = file_.Rename(new_path); | 152 DownloadInterruptReason reason = file_.Rename(new_path); |
161 | 153 |
162 // Attempt to retry the rename if possible. If the rename failed and the | 154 // Attempt to retry the rename if possible. If the rename failed and the |
163 // subsequent open also failed, then in_progress() would be false. We don't | 155 // subsequent open also failed, then in_progress() would be false. We don't |
164 // try to retry renames if the in_progress() was false to begin with since we | 156 // try to retry renames if the in_progress() was false to begin with since we |
165 // have less assurance that the file at file_.full_path() was the one we were | 157 // have less assurance that the file at file_.full_path() was the one we were |
166 // working with. | 158 // working with. |
167 if (ShouldRetryFailedRename(reason) && file_.in_progress() && | 159 if (ShouldRetryFailedRename(reason) && file_.in_progress() && |
168 retries_left > 0) { | 160 parameters->retries_left > 0) { |
169 int attempt_number = kMaxRenameRetries - retries_left; | 161 int attempt_number = kMaxRenameRetries - parameters->retries_left; |
| 162 --parameters->retries_left; |
| 163 if (parameters->time_of_first_failure.is_null()) |
| 164 parameters->time_of_first_failure = base::TimeTicks::Now(); |
170 BrowserThread::PostDelayedTask( | 165 BrowserThread::PostDelayedTask( |
171 BrowserThread::FILE, | 166 BrowserThread::FILE, FROM_HERE, |
172 FROM_HERE, | |
173 base::Bind(&DownloadFileImpl::RenameWithRetryInternal, | 167 base::Bind(&DownloadFileImpl::RenameWithRetryInternal, |
174 weak_factory_.GetWeakPtr(), | 168 weak_factory_.GetWeakPtr(), |
175 full_path, | 169 base::Passed(std::move(parameters))), |
176 option, | |
177 --retries_left, | |
178 time_of_first_failure.is_null() ? base::TimeTicks::Now() | |
179 : time_of_first_failure, | |
180 callback), | |
181 GetRetryDelayForFailedRename(attempt_number)); | 170 GetRetryDelayForFailedRename(attempt_number)); |
182 return; | 171 return; |
183 } | 172 } |
184 | 173 |
185 if (!time_of_first_failure.is_null()) | 174 if (!parameters->time_of_first_failure.is_null()) |
186 RecordDownloadFileRenameResultAfterRetry( | 175 RecordDownloadFileRenameResultAfterRetry( |
187 base::TimeTicks::Now() - time_of_first_failure, reason); | 176 base::TimeTicks::Now() - parameters->time_of_first_failure, reason); |
188 | 177 |
189 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE && | 178 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE && |
190 (option & ANNOTATE_WITH_SOURCE_INFORMATION)) { | 179 (parameters->option & ANNOTATE_WITH_SOURCE_INFORMATION)) { |
191 // Doing the annotation after the rename rather than before leaves | 180 // Doing the annotation after the rename rather than before leaves |
192 // a very small window during which the file has the final name but | 181 // a very small window during which the file has the final name but |
193 // hasn't been marked with the Mark Of The Web. However, it allows | 182 // hasn't been marked with the Mark Of The Web. However, it allows |
194 // anti-virus scanners on Windows to actually see the data | 183 // anti-virus scanners on Windows to actually see the data |
195 // (http://crbug.com/127999) under the correct name (which is information | 184 // (http://crbug.com/127999) under the correct name (which is information |
196 // it uses). | 185 // it uses). |
197 reason = file_.AnnotateWithSourceInformation(); | 186 reason = file_.AnnotateWithSourceInformation(parameters->client_guid, |
| 187 parameters->source_url, |
| 188 parameters->referrer_url); |
198 } | 189 } |
199 | 190 |
200 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 191 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
201 // Make sure our information is updated, since we're about to | 192 // Make sure our information is updated, since we're about to |
202 // error out. | 193 // error out. |
203 SendUpdate(); | 194 SendUpdate(); |
204 | 195 |
205 // Null out callback so that we don't do any more stream processing. | 196 // Null out callback so that we don't do any more stream processing. |
206 stream_reader_->RegisterCallback(base::Closure()); | 197 stream_reader_->RegisterCallback(base::Closure()); |
207 | 198 |
208 new_path.clear(); | 199 new_path.clear(); |
209 } | 200 } |
210 | 201 |
211 BrowserThread::PostTask( | 202 BrowserThread::PostTask( |
212 BrowserThread::UI, FROM_HERE, | 203 BrowserThread::UI, FROM_HERE, |
213 base::Bind(callback, reason, new_path)); | 204 base::Bind(parameters->completion_callback, reason, new_path)); |
214 } | 205 } |
215 | 206 |
216 void DownloadFileImpl::Detach() { | 207 void DownloadFileImpl::Detach() { |
217 file_.Detach(); | 208 file_.Detach(); |
218 } | 209 } |
219 | 210 |
220 void DownloadFileImpl::Cancel() { | 211 void DownloadFileImpl::Cancel() { |
221 file_.Cancel(); | 212 file_.Cancel(); |
222 } | 213 } |
223 | 214 |
224 base::FilePath DownloadFileImpl::FullPath() const { | 215 const base::FilePath& DownloadFileImpl::FullPath() const { |
225 return file_.full_path(); | 216 return file_.full_path(); |
226 } | 217 } |
227 | 218 |
228 bool DownloadFileImpl::InProgress() const { | 219 bool DownloadFileImpl::InProgress() const { |
229 return file_.in_progress(); | 220 return file_.in_progress(); |
230 } | 221 } |
231 | 222 |
232 int64_t DownloadFileImpl::CurrentSpeed() const { | |
233 return rate_estimator_.GetCountPerSecond(); | |
234 } | |
235 | |
236 bool DownloadFileImpl::GetHash(std::string* hash) { | |
237 return file_.GetHash(hash); | |
238 } | |
239 | |
240 std::string DownloadFileImpl::GetHashState() { | |
241 return file_.GetHashState(); | |
242 } | |
243 | |
244 void DownloadFileImpl::SetClientGuid(const std::string& guid) { | |
245 file_.SetClientGuid(guid); | |
246 } | |
247 | |
248 void DownloadFileImpl::StreamActive() { | 223 void DownloadFileImpl::StreamActive() { |
249 base::TimeTicks start(base::TimeTicks::Now()); | 224 base::TimeTicks start(base::TimeTicks::Now()); |
250 base::TimeTicks now; | 225 base::TimeTicks now; |
251 scoped_refptr<net::IOBuffer> incoming_data; | 226 scoped_refptr<net::IOBuffer> incoming_data; |
252 size_t incoming_data_size = 0; | 227 size_t incoming_data_size = 0; |
253 size_t total_incoming_data_size = 0; | 228 size_t total_incoming_data_size = 0; |
254 size_t num_buffers = 0; | 229 size_t num_buffers = 0; |
255 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); | 230 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); |
256 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; | 231 DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; |
257 base::TimeDelta delta( | 232 base::TimeDelta delta( |
(...skipping 16 matching lines...) Expand all Loading... |
274 bytes_seen_ += incoming_data_size; | 249 bytes_seen_ += incoming_data_size; |
275 total_incoming_data_size += incoming_data_size; | 250 total_incoming_data_size += incoming_data_size; |
276 } | 251 } |
277 break; | 252 break; |
278 case ByteStreamReader::STREAM_COMPLETE: | 253 case ByteStreamReader::STREAM_COMPLETE: |
279 { | 254 { |
280 reason = static_cast<DownloadInterruptReason>( | 255 reason = static_cast<DownloadInterruptReason>( |
281 stream_reader_->GetStatus()); | 256 stream_reader_->GetStatus()); |
282 SendUpdate(); | 257 SendUpdate(); |
283 base::TimeTicks close_start(base::TimeTicks::Now()); | 258 base::TimeTicks close_start(base::TimeTicks::Now()); |
284 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) | |
285 file_.Finish(); | |
286 else | |
287 file_.FinishWithError(); | |
288 base::TimeTicks now(base::TimeTicks::Now()); | 259 base::TimeTicks now(base::TimeTicks::Now()); |
289 disk_writes_time_ += (now - close_start); | 260 disk_writes_time_ += (now - close_start); |
290 RecordFileBandwidth( | 261 RecordFileBandwidth( |
291 bytes_seen_, disk_writes_time_, now - download_start_); | 262 bytes_seen_, disk_writes_time_, now - download_start_); |
292 update_timer_.reset(); | 263 update_timer_.reset(); |
293 } | 264 } |
294 break; | 265 break; |
295 default: | 266 default: |
296 NOTREACHED(); | 267 NOTREACHED(); |
297 break; | 268 break; |
(...skipping 17 matching lines...) Expand all Loading... |
315 | 286 |
316 RecordContiguousWriteTime(now - start); | 287 RecordContiguousWriteTime(now - start); |
317 | 288 |
318 // Take care of communication with our observer. | 289 // Take care of communication with our observer. |
319 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 290 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
320 // Error case for both upstream source and file write. | 291 // Error case for both upstream source and file write. |
321 // Shut down processing and signal an error to our observer. | 292 // Shut down processing and signal an error to our observer. |
322 // Our observer will clean us up. | 293 // Our observer will clean us up. |
323 stream_reader_->RegisterCallback(base::Closure()); | 294 stream_reader_->RegisterCallback(base::Closure()); |
324 weak_factory_.InvalidateWeakPtrs(); | 295 weak_factory_.InvalidateWeakPtrs(); |
325 SendUpdate(); // Make info up to date before error. | 296 SendUpdate(); // Make info up to date before error. |
| 297 scoped_ptr<crypto::SecureHash> hash_state = file_.Finish(); |
326 BrowserThread::PostTask( | 298 BrowserThread::PostTask( |
327 BrowserThread::UI, FROM_HERE, | 299 BrowserThread::UI, FROM_HERE, |
328 base::Bind(&DownloadDestinationObserver::DestinationError, | 300 base::Bind(&DownloadDestinationObserver::DestinationError, observer_, |
329 observer_, reason)); | 301 reason, file_.bytes_so_far(), base::Passed(&hash_state))); |
330 } else if (state == ByteStreamReader::STREAM_COMPLETE) { | 302 } else if (state == ByteStreamReader::STREAM_COMPLETE) { |
331 // Signal successful completion and shut down processing. | 303 // Signal successful completion and shut down processing. |
332 stream_reader_->RegisterCallback(base::Closure()); | 304 stream_reader_->RegisterCallback(base::Closure()); |
333 weak_factory_.InvalidateWeakPtrs(); | 305 weak_factory_.InvalidateWeakPtrs(); |
334 std::string hash; | |
335 if (!GetHash(&hash) || file_.IsEmptyHash(hash)) | |
336 hash.clear(); | |
337 SendUpdate(); | 306 SendUpdate(); |
| 307 scoped_ptr<crypto::SecureHash> hash_state = file_.Finish(); |
338 BrowserThread::PostTask( | 308 BrowserThread::PostTask( |
339 BrowserThread::UI, FROM_HERE, | 309 BrowserThread::UI, FROM_HERE, |
340 base::Bind( | 310 base::Bind(&DownloadDestinationObserver::DestinationCompleted, |
341 &DownloadDestinationObserver::DestinationCompleted, | 311 observer_, file_.bytes_so_far(), base::Passed(&hash_state))); |
342 observer_, hash)); | |
343 } | 312 } |
344 if (bound_net_log_.IsCapturing()) { | 313 if (bound_net_log_.IsCapturing()) { |
345 bound_net_log_.AddEvent( | 314 bound_net_log_.AddEvent( |
346 net::NetLog::TYPE_DOWNLOAD_STREAM_DRAINED, | 315 net::NetLog::TYPE_DOWNLOAD_STREAM_DRAINED, |
347 base::Bind(&FileStreamDrainedNetLogCallback, total_incoming_data_size, | 316 base::Bind(&FileStreamDrainedNetLogCallback, total_incoming_data_size, |
348 num_buffers)); | 317 num_buffers)); |
349 } | 318 } |
350 } | 319 } |
351 | 320 |
352 void DownloadFileImpl::SendUpdate() { | 321 void DownloadFileImpl::SendUpdate() { |
353 BrowserThread::PostTask( | 322 BrowserThread::PostTask( |
354 BrowserThread::UI, FROM_HERE, | 323 BrowserThread::UI, FROM_HERE, |
355 base::Bind(&DownloadDestinationObserver::DestinationUpdate, | 324 base::Bind(&DownloadDestinationObserver::DestinationUpdate, observer_, |
356 observer_, file_.bytes_so_far(), CurrentSpeed(), | 325 file_.bytes_so_far(), rate_estimator_.GetCountPerSecond())); |
357 GetHashState())); | |
358 } | 326 } |
359 | 327 |
360 // static | 328 DownloadFileImpl::RenameParameters::RenameParameters( |
361 int DownloadFile::GetNumberOfDownloadFiles() { | 329 RenameOption option, |
362 return number_active_objects_; | 330 const base::FilePath& new_path, |
363 } | 331 const RenameCompletionCallback& completion_callback) |
| 332 : option(option), |
| 333 new_path(new_path), |
| 334 retries_left(kMaxRenameRetries), |
| 335 completion_callback(completion_callback) {} |
| 336 |
| 337 DownloadFileImpl::RenameParameters::~RenameParameters() {} |
364 | 338 |
365 } // namespace content | 339 } // namespace content |
OLD | NEW |