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