| 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/base_file.h" | 5 #include "content/browser/download/base_file.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file.h" | 10 #include "base/files/file.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "content/browser/download/quarantine.h" | 21 #include "content/browser/download/quarantine.h" |
| 22 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/browser/content_browser_client.h" | 23 #include "content/public/browser/content_browser_client.h" |
| 24 #include "crypto/secure_hash.h" | 24 #include "crypto/secure_hash.h" |
| 25 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
| 26 #include "net/log/net_log.h" | 26 #include "net/log/net_log.h" |
| 27 #include "net/log/net_log_event_type.h" | 27 #include "net/log/net_log_event_type.h" |
| 28 | 28 |
| 29 namespace content { | 29 namespace content { |
| 30 | 30 |
| 31 BaseFile::BaseFile(const net::BoundNetLog& bound_net_log) | 31 BaseFile::BaseFile(const net::NetLogWithSource& net_log) : net_log_(net_log) {} |
| 32 : bound_net_log_(bound_net_log) {} | |
| 33 | 32 |
| 34 BaseFile::~BaseFile() { | 33 BaseFile::~BaseFile() { |
| 35 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 34 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 36 if (detached_) | 35 if (detached_) |
| 37 Close(); | 36 Close(); |
| 38 else | 37 else |
| 39 Cancel(); // Will delete the file. | 38 Cancel(); // Will delete the file. |
| 40 } | 39 } |
| 41 | 40 |
| 42 DownloadInterruptReason BaseFile::Initialize( | 41 DownloadInterruptReason BaseFile::Initialize( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 90 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 92 | 91 |
| 93 // TODO(phajdan.jr): get rid of this check. | 92 // TODO(phajdan.jr): get rid of this check. |
| 94 if (data_len == 0) | 93 if (data_len == 0) |
| 95 return DOWNLOAD_INTERRUPT_REASON_NONE; | 94 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 96 | 95 |
| 97 // The Write call below is not guaranteed to write all the data. | 96 // The Write call below is not guaranteed to write all the data. |
| 98 size_t write_count = 0; | 97 size_t write_count = 0; |
| 99 size_t len = data_len; | 98 size_t len = data_len; |
| 100 const char* current_data = data; | 99 const char* current_data = data; |
| 101 bound_net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN); | 100 net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN); |
| 102 while (len > 0) { | 101 while (len > 0) { |
| 103 write_count++; | 102 write_count++; |
| 104 int write_result = file_.WriteAtCurrentPos(current_data, len); | 103 int write_result = file_.WriteAtCurrentPos(current_data, len); |
| 105 DCHECK_NE(0, write_result); | 104 DCHECK_NE(0, write_result); |
| 106 | 105 |
| 107 // Report errors on file writes. | 106 // Report errors on file writes. |
| 108 if (write_result < 0) | 107 if (write_result < 0) |
| 109 return LogSystemError("Write", logging::GetLastSystemErrorCode()); | 108 return LogSystemError("Write", logging::GetLastSystemErrorCode()); |
| 110 | 109 |
| 111 // Update status. | 110 // Update status. |
| 112 size_t write_size = static_cast<size_t>(write_result); | 111 size_t write_size = static_cast<size_t>(write_result); |
| 113 DCHECK_LE(write_size, len); | 112 DCHECK_LE(write_size, len); |
| 114 len -= write_size; | 113 len -= write_size; |
| 115 current_data += write_size; | 114 current_data += write_size; |
| 116 bytes_so_far_ += write_size; | 115 bytes_so_far_ += write_size; |
| 117 } | 116 } |
| 118 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, | 117 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, |
| 119 net::NetLog::Int64Callback("bytes", data_len)); | 118 net::NetLog::Int64Callback("bytes", data_len)); |
| 120 | 119 |
| 121 RecordDownloadWriteSize(data_len); | 120 RecordDownloadWriteSize(data_len); |
| 122 RecordDownloadWriteLoopCount(write_count); | 121 RecordDownloadWriteLoopCount(write_count); |
| 123 | 122 |
| 124 if (secure_hash_) | 123 if (secure_hash_) |
| 125 secure_hash_->Update(data, data_len); | 124 secure_hash_->Update(data, data_len); |
| 126 | 125 |
| 127 return DOWNLOAD_INTERRUPT_REASON_NONE; | 126 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 128 } | 127 } |
| 129 | 128 |
| 130 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { | 129 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { |
| 131 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 130 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 132 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 131 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 133 | 132 |
| 134 // If the new path is same as the old one, there is no need to perform the | 133 // If the new path is same as the old one, there is no need to perform the |
| 135 // following renaming logic. | 134 // following renaming logic. |
| 136 if (new_path == full_path_) | 135 if (new_path == full_path_) |
| 137 return DOWNLOAD_INTERRUPT_REASON_NONE; | 136 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 138 | 137 |
| 139 // Save the information whether the download is in progress because | 138 // Save the information whether the download is in progress because |
| 140 // it will be overwritten by closing the file. | 139 // it will be overwritten by closing the file. |
| 141 bool was_in_progress = in_progress(); | 140 bool was_in_progress = in_progress(); |
| 142 | 141 |
| 143 Close(); | 142 Close(); |
| 144 | 143 |
| 145 bound_net_log_.BeginEvent( | 144 net_log_.BeginEvent( |
| 146 net::NetLogEventType::DOWNLOAD_FILE_RENAMED, | 145 net::NetLogEventType::DOWNLOAD_FILE_RENAMED, |
| 147 base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path)); | 146 base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path)); |
| 148 | 147 |
| 149 base::CreateDirectory(new_path.DirName()); | 148 base::CreateDirectory(new_path.DirName()); |
| 150 | 149 |
| 151 // A simple rename wouldn't work here since we want the file to have | 150 // A simple rename wouldn't work here since we want the file to have |
| 152 // permissions / security descriptors that makes sense in the new directory. | 151 // permissions / security descriptors that makes sense in the new directory. |
| 153 rename_result = MoveFileAndAdjustPermissions(new_path); | 152 rename_result = MoveFileAndAdjustPermissions(new_path); |
| 154 | 153 |
| 155 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_RENAMED); | 154 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_RENAMED); |
| 156 | 155 |
| 157 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) | 156 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) |
| 158 full_path_ = new_path; | 157 full_path_ = new_path; |
| 159 | 158 |
| 160 // Re-open the file if we were still using it regardless of the interrupt | 159 // Re-open the file if we were still using it regardless of the interrupt |
| 161 // reason. | 160 // reason. |
| 162 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 161 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 163 if (was_in_progress) | 162 if (was_in_progress) |
| 164 open_result = Open(std::string()); | 163 open_result = Open(std::string()); |
| 165 | 164 |
| 166 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result | 165 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result |
| 167 : rename_result; | 166 : rename_result; |
| 168 } | 167 } |
| 169 | 168 |
| 170 void BaseFile::Detach() { | 169 void BaseFile::Detach() { |
| 171 detached_ = true; | 170 detached_ = true; |
| 172 bound_net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DETACHED); | 171 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DETACHED); |
| 173 } | 172 } |
| 174 | 173 |
| 175 void BaseFile::Cancel() { | 174 void BaseFile::Cancel() { |
| 176 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 175 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 177 DCHECK(!detached_); | 176 DCHECK(!detached_); |
| 178 | 177 |
| 179 bound_net_log_.AddEvent(net::NetLogEventType::CANCELLED); | 178 net_log_.AddEvent(net::NetLogEventType::CANCELLED); |
| 180 | 179 |
| 181 Close(); | 180 Close(); |
| 182 | 181 |
| 183 if (!full_path_.empty()) { | 182 if (!full_path_.empty()) { |
| 184 bound_net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DELETED); | 183 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DELETED); |
| 185 base::DeleteFile(full_path_, false); | 184 base::DeleteFile(full_path_, false); |
| 186 } | 185 } |
| 187 | 186 |
| 188 Detach(); | 187 Detach(); |
| 189 } | 188 } |
| 190 | 189 |
| 191 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { | 190 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { |
| 192 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 191 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 193 Close(); | 192 Close(); |
| 194 return std::move(secure_hash_); | 193 return std::move(secure_hash_); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 if (!file_.IsValid()) { | 280 if (!file_.IsValid()) { |
| 282 file_.Initialize(full_path_, | 281 file_.Initialize(full_path_, |
| 283 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE | | 282 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE | |
| 284 base::File::FLAG_READ); | 283 base::File::FLAG_READ); |
| 285 if (!file_.IsValid()) { | 284 if (!file_.IsValid()) { |
| 286 return LogNetError("Open/Initialize File", | 285 return LogNetError("Open/Initialize File", |
| 287 net::FileErrorToNetError(file_.error_details())); | 286 net::FileErrorToNetError(file_.error_details())); |
| 288 } | 287 } |
| 289 } | 288 } |
| 290 | 289 |
| 291 bound_net_log_.BeginEvent( | 290 net_log_.BeginEvent( |
| 292 net::NetLogEventType::DOWNLOAD_FILE_OPENED, | 291 net::NetLogEventType::DOWNLOAD_FILE_OPENED, |
| 293 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); | 292 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); |
| 294 | 293 |
| 295 if (!secure_hash_) { | 294 if (!secure_hash_) { |
| 296 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); | 295 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); |
| 297 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 296 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 298 ClearFile(); | 297 ClearFile(); |
| 299 return reason; | 298 return reason; |
| 300 } | 299 } |
| 301 } | 300 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // theres not much we can do. But we might in the future. | 332 // theres not much we can do. But we might in the future. |
| 334 file_.Flush(); | 333 file_.Flush(); |
| 335 ClearFile(); | 334 ClearFile(); |
| 336 } | 335 } |
| 337 } | 336 } |
| 338 | 337 |
| 339 void BaseFile::ClearFile() { | 338 void BaseFile::ClearFile() { |
| 340 // This should only be called when we have a stream. | 339 // This should only be called when we have a stream. |
| 341 DCHECK(file_.IsValid()); | 340 DCHECK(file_.IsValid()); |
| 342 file_.Close(); | 341 file_.Close(); |
| 343 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_OPENED); | 342 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_OPENED); |
| 344 } | 343 } |
| 345 | 344 |
| 346 DownloadInterruptReason BaseFile::LogNetError( | 345 DownloadInterruptReason BaseFile::LogNetError( |
| 347 const char* operation, | 346 const char* operation, |
| 348 net::Error error) { | 347 net::Error error) { |
| 349 bound_net_log_.AddEvent( | 348 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_ERROR, |
| 350 net::NetLogEventType::DOWNLOAD_FILE_ERROR, | 349 base::Bind(&FileErrorNetLogCallback, operation, error)); |
| 351 base::Bind(&FileErrorNetLogCallback, operation, error)); | |
| 352 return ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_DISK); | 350 return ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_DISK); |
| 353 } | 351 } |
| 354 | 352 |
| 355 DownloadInterruptReason BaseFile::LogSystemError( | 353 DownloadInterruptReason BaseFile::LogSystemError( |
| 356 const char* operation, | 354 const char* operation, |
| 357 logging::SystemErrorCode os_error) { | 355 logging::SystemErrorCode os_error) { |
| 358 // There's no direct conversion from a system error to an interrupt reason. | 356 // There's no direct conversion from a system error to an interrupt reason. |
| 359 base::File::Error file_error = base::File::OSErrorToFileError(os_error); | 357 base::File::Error file_error = base::File::OSErrorToFileError(os_error); |
| 360 return LogInterruptReason( | 358 return LogInterruptReason( |
| 361 operation, os_error, | 359 operation, os_error, |
| 362 ConvertFileErrorToInterruptReason(file_error)); | 360 ConvertFileErrorToInterruptReason(file_error)); |
| 363 } | 361 } |
| 364 | 362 |
| 365 DownloadInterruptReason BaseFile::LogInterruptReason( | 363 DownloadInterruptReason BaseFile::LogInterruptReason( |
| 366 const char* operation, | 364 const char* operation, |
| 367 int os_error, | 365 int os_error, |
| 368 DownloadInterruptReason reason) { | 366 DownloadInterruptReason reason) { |
| 369 DVLOG(1) << __func__ << "() operation:" << operation | 367 DVLOG(1) << __func__ << "() operation:" << operation |
| 370 << " os_error:" << os_error | 368 << " os_error:" << os_error |
| 371 << " reason:" << DownloadInterruptReasonToString(reason); | 369 << " reason:" << DownloadInterruptReasonToString(reason); |
| 372 bound_net_log_.AddEvent( | 370 net_log_.AddEvent( |
| 373 net::NetLogEventType::DOWNLOAD_FILE_ERROR, | 371 net::NetLogEventType::DOWNLOAD_FILE_ERROR, |
| 374 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); | 372 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); |
| 375 return reason; | 373 return reason; |
| 376 } | 374 } |
| 377 | 375 |
| 378 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) | 376 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) |
| 379 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( | 377 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( |
| 380 const std::string& client_guid, | 378 const std::string& client_guid, |
| 381 const GURL& source_url, | 379 const GURL& source_url, |
| 382 const GURL& referrer_url) { | 380 const GURL& referrer_url) { |
| 383 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 381 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 384 DCHECK(!detached_); | 382 DCHECK(!detached_); |
| 385 DCHECK(!full_path_.empty()); | 383 DCHECK(!full_path_.empty()); |
| 386 | 384 |
| 387 bound_net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_ANNOTATED); | 385 net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_ANNOTATED); |
| 388 QuarantineFileResult result = | 386 QuarantineFileResult result = |
| 389 QuarantineFile(full_path_, source_url, referrer_url, client_guid); | 387 QuarantineFile(full_path_, source_url, referrer_url, client_guid); |
| 390 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ANNOTATED); | 388 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ANNOTATED); |
| 391 switch (result) { | 389 switch (result) { |
| 392 case QuarantineFileResult::OK: | 390 case QuarantineFileResult::OK: |
| 393 return DOWNLOAD_INTERRUPT_REASON_NONE; | 391 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 394 case QuarantineFileResult::VIRUS_INFECTED: | 392 case QuarantineFileResult::VIRUS_INFECTED: |
| 395 return DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED; | 393 return DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED; |
| 396 case QuarantineFileResult::SECURITY_CHECK_FAILED: | 394 case QuarantineFileResult::SECURITY_CHECK_FAILED: |
| 397 return DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED; | 395 return DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED; |
| 398 case QuarantineFileResult::BLOCKED_BY_POLICY: | 396 case QuarantineFileResult::BLOCKED_BY_POLICY: |
| 399 return DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED; | 397 return DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED; |
| 400 case QuarantineFileResult::ACCESS_DENIED: | 398 case QuarantineFileResult::ACCESS_DENIED: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 426 #else // !OS_WIN && !OS_MACOSX && !OS_LINUX | 424 #else // !OS_WIN && !OS_MACOSX && !OS_LINUX |
| 427 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( | 425 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( |
| 428 const std::string& client_guid, | 426 const std::string& client_guid, |
| 429 const GURL& source_url, | 427 const GURL& source_url, |
| 430 const GURL& referrer_url) { | 428 const GURL& referrer_url) { |
| 431 return DOWNLOAD_INTERRUPT_REASON_NONE; | 429 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 432 } | 430 } |
| 433 #endif | 431 #endif |
| 434 | 432 |
| 435 } // namespace content | 433 } // namespace content |
| OLD | NEW |