| 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" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/pickle.h" | 14 #include "base/pickle.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "base/threading/thread_restrictions.h" | 16 #include "base/threading/thread_restrictions.h" |
| 17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 18 #include "content/browser/download/download_interrupt_reasons_impl.h" | 18 #include "content/browser/download/download_interrupt_reasons_impl.h" |
| 19 #include "content/browser/download/download_net_log_parameters.h" | 19 #include "content/browser/download/download_net_log_parameters.h" |
| 20 #include "content/browser/download/download_stats.h" | 20 #include "content/browser/download/download_stats.h" |
| 21 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 22 #include "content/public/browser/content_browser_client.h" | 22 #include "content/public/browser/content_browser_client.h" |
| 23 #include "crypto/secure_hash.h" | 23 #include "crypto/secure_hash.h" |
| 24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 25 #include "net/log/net_log.h" | 25 #include "net/log/net_log.h" |
| 26 #include "net/log/net_log_event_type.h" |
| 26 | 27 |
| 27 namespace content { | 28 namespace content { |
| 28 | 29 |
| 29 BaseFile::BaseFile(const net::BoundNetLog& bound_net_log) | 30 BaseFile::BaseFile(const net::BoundNetLog& bound_net_log) |
| 30 : bound_net_log_(bound_net_log) {} | 31 : bound_net_log_(bound_net_log) {} |
| 31 | 32 |
| 32 BaseFile::~BaseFile() { | 33 BaseFile::~BaseFile() { |
| 33 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 34 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 34 if (detached_) | 35 if (detached_) |
| 35 Close(); | 36 Close(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 90 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 90 | 91 |
| 91 // TODO(phajdan.jr): get rid of this check. | 92 // TODO(phajdan.jr): get rid of this check. |
| 92 if (data_len == 0) | 93 if (data_len == 0) |
| 93 return DOWNLOAD_INTERRUPT_REASON_NONE; | 94 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 94 | 95 |
| 95 // 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. |
| 96 size_t write_count = 0; | 97 size_t write_count = 0; |
| 97 size_t len = data_len; | 98 size_t len = data_len; |
| 98 const char* current_data = data; | 99 const char* current_data = data; |
| 99 bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_WRITTEN); | 100 bound_net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN); |
| 100 while (len > 0) { | 101 while (len > 0) { |
| 101 write_count++; | 102 write_count++; |
| 102 int write_result = file_.WriteAtCurrentPos(current_data, len); | 103 int write_result = file_.WriteAtCurrentPos(current_data, len); |
| 103 DCHECK_NE(0, write_result); | 104 DCHECK_NE(0, write_result); |
| 104 | 105 |
| 105 // Report errors on file writes. | 106 // Report errors on file writes. |
| 106 if (write_result < 0) | 107 if (write_result < 0) |
| 107 return LogSystemError("Write", logging::GetLastSystemErrorCode()); | 108 return LogSystemError("Write", logging::GetLastSystemErrorCode()); |
| 108 | 109 |
| 109 // Update status. | 110 // Update status. |
| 110 size_t write_size = static_cast<size_t>(write_result); | 111 size_t write_size = static_cast<size_t>(write_result); |
| 111 DCHECK_LE(write_size, len); | 112 DCHECK_LE(write_size, len); |
| 112 len -= write_size; | 113 len -= write_size; |
| 113 current_data += write_size; | 114 current_data += write_size; |
| 114 bytes_so_far_ += write_size; | 115 bytes_so_far_ += write_size; |
| 115 } | 116 } |
| 116 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_WRITTEN, | 117 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, |
| 117 net::NetLog::Int64Callback("bytes", data_len)); | 118 net::NetLog::Int64Callback("bytes", data_len)); |
| 118 | 119 |
| 119 RecordDownloadWriteSize(data_len); | 120 RecordDownloadWriteSize(data_len); |
| 120 RecordDownloadWriteLoopCount(write_count); | 121 RecordDownloadWriteLoopCount(write_count); |
| 121 | 122 |
| 122 if (secure_hash_) | 123 if (secure_hash_) |
| 123 secure_hash_->Update(data, data_len); | 124 secure_hash_->Update(data, data_len); |
| 124 | 125 |
| 125 return DOWNLOAD_INTERRUPT_REASON_NONE; | 126 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 126 } | 127 } |
| 127 | 128 |
| 128 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { | 129 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { |
| 129 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 130 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 130 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 131 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 131 | 132 |
| 132 // 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 |
| 133 // following renaming logic. | 134 // following renaming logic. |
| 134 if (new_path == full_path_) | 135 if (new_path == full_path_) |
| 135 return DOWNLOAD_INTERRUPT_REASON_NONE; | 136 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 136 | 137 |
| 137 // Save the information whether the download is in progress because | 138 // Save the information whether the download is in progress because |
| 138 // it will be overwritten by closing the file. | 139 // it will be overwritten by closing the file. |
| 139 bool was_in_progress = in_progress(); | 140 bool was_in_progress = in_progress(); |
| 140 | 141 |
| 141 Close(); | 142 Close(); |
| 142 | 143 |
| 143 bound_net_log_.BeginEvent( | 144 bound_net_log_.BeginEvent( |
| 144 net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED, | 145 net::NetLogEventType::DOWNLOAD_FILE_RENAMED, |
| 145 base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path)); | 146 base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path)); |
| 146 | 147 |
| 147 base::CreateDirectory(new_path.DirName()); | 148 base::CreateDirectory(new_path.DirName()); |
| 148 | 149 |
| 149 // 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 |
| 150 // permissions / security descriptors that makes sense in the new directory. | 151 // permissions / security descriptors that makes sense in the new directory. |
| 151 rename_result = MoveFileAndAdjustPermissions(new_path); | 152 rename_result = MoveFileAndAdjustPermissions(new_path); |
| 152 | 153 |
| 153 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED); | 154 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_RENAMED); |
| 154 | 155 |
| 155 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) | 156 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) |
| 156 full_path_ = new_path; | 157 full_path_ = new_path; |
| 157 | 158 |
| 158 // 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 |
| 159 // reason. | 160 // reason. |
| 160 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 161 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 161 if (was_in_progress) | 162 if (was_in_progress) |
| 162 open_result = Open(std::string()); | 163 open_result = Open(std::string()); |
| 163 | 164 |
| 164 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result | 165 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result |
| 165 : rename_result; | 166 : rename_result; |
| 166 } | 167 } |
| 167 | 168 |
| 168 void BaseFile::Detach() { | 169 void BaseFile::Detach() { |
| 169 detached_ = true; | 170 detached_ = true; |
| 170 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DETACHED); | 171 bound_net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DETACHED); |
| 171 } | 172 } |
| 172 | 173 |
| 173 void BaseFile::Cancel() { | 174 void BaseFile::Cancel() { |
| 174 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 175 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 175 DCHECK(!detached_); | 176 DCHECK(!detached_); |
| 176 | 177 |
| 177 bound_net_log_.AddEvent(net::NetLog::TYPE_CANCELLED); | 178 bound_net_log_.AddEvent(net::NetLogEventType::CANCELLED); |
| 178 | 179 |
| 179 Close(); | 180 Close(); |
| 180 | 181 |
| 181 if (!full_path_.empty()) { | 182 if (!full_path_.empty()) { |
| 182 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DELETED); | 183 bound_net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DELETED); |
| 183 base::DeleteFile(full_path_, false); | 184 base::DeleteFile(full_path_, false); |
| 184 } | 185 } |
| 185 | 186 |
| 186 Detach(); | 187 Detach(); |
| 187 } | 188 } |
| 188 | 189 |
| 189 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { | 190 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { |
| 190 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 191 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 191 Close(); | 192 Close(); |
| 192 return std::move(secure_hash_); | 193 return std::move(secure_hash_); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 file_.Initialize(full_path_, | 291 file_.Initialize(full_path_, |
| 291 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE | | 292 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE | |
| 292 base::File::FLAG_READ); | 293 base::File::FLAG_READ); |
| 293 if (!file_.IsValid()) { | 294 if (!file_.IsValid()) { |
| 294 return LogNetError("Open/Initialize File", | 295 return LogNetError("Open/Initialize File", |
| 295 net::FileErrorToNetError(file_.error_details())); | 296 net::FileErrorToNetError(file_.error_details())); |
| 296 } | 297 } |
| 297 } | 298 } |
| 298 | 299 |
| 299 bound_net_log_.BeginEvent( | 300 bound_net_log_.BeginEvent( |
| 300 net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, | 301 net::NetLogEventType::DOWNLOAD_FILE_OPENED, |
| 301 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); | 302 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); |
| 302 | 303 |
| 303 if (!secure_hash_) { | 304 if (!secure_hash_) { |
| 304 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); | 305 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); |
| 305 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 306 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 306 ClearFile(); | 307 ClearFile(); |
| 307 return reason; | 308 return reason; |
| 308 } | 309 } |
| 309 } | 310 } |
| 310 | 311 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 341 // theres not much we can do. But we might in the future. | 342 // theres not much we can do. But we might in the future. |
| 342 file_.Flush(); | 343 file_.Flush(); |
| 343 ClearFile(); | 344 ClearFile(); |
| 344 } | 345 } |
| 345 } | 346 } |
| 346 | 347 |
| 347 void BaseFile::ClearFile() { | 348 void BaseFile::ClearFile() { |
| 348 // This should only be called when we have a stream. | 349 // This should only be called when we have a stream. |
| 349 DCHECK(file_.IsValid()); | 350 DCHECK(file_.IsValid()); |
| 350 file_.Close(); | 351 file_.Close(); |
| 351 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_OPENED); | 352 bound_net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_OPENED); |
| 352 } | 353 } |
| 353 | 354 |
| 354 DownloadInterruptReason BaseFile::LogNetError( | 355 DownloadInterruptReason BaseFile::LogNetError( |
| 355 const char* operation, | 356 const char* operation, |
| 356 net::Error error) { | 357 net::Error error) { |
| 357 bound_net_log_.AddEvent( | 358 bound_net_log_.AddEvent( |
| 358 net::NetLog::TYPE_DOWNLOAD_FILE_ERROR, | 359 net::NetLogEventType::DOWNLOAD_FILE_ERROR, |
| 359 base::Bind(&FileErrorNetLogCallback, operation, error)); | 360 base::Bind(&FileErrorNetLogCallback, operation, error)); |
| 360 return ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_DISK); | 361 return ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_DISK); |
| 361 } | 362 } |
| 362 | 363 |
| 363 DownloadInterruptReason BaseFile::LogSystemError( | 364 DownloadInterruptReason BaseFile::LogSystemError( |
| 364 const char* operation, | 365 const char* operation, |
| 365 logging::SystemErrorCode os_error) { | 366 logging::SystemErrorCode os_error) { |
| 366 // There's no direct conversion from a system error to an interrupt reason. | 367 // There's no direct conversion from a system error to an interrupt reason. |
| 367 base::File::Error file_error = base::File::OSErrorToFileError(os_error); | 368 base::File::Error file_error = base::File::OSErrorToFileError(os_error); |
| 368 return LogInterruptReason( | 369 return LogInterruptReason( |
| 369 operation, os_error, | 370 operation, os_error, |
| 370 ConvertFileErrorToInterruptReason(file_error)); | 371 ConvertFileErrorToInterruptReason(file_error)); |
| 371 } | 372 } |
| 372 | 373 |
| 373 DownloadInterruptReason BaseFile::LogInterruptReason( | 374 DownloadInterruptReason BaseFile::LogInterruptReason( |
| 374 const char* operation, | 375 const char* operation, |
| 375 int os_error, | 376 int os_error, |
| 376 DownloadInterruptReason reason) { | 377 DownloadInterruptReason reason) { |
| 377 DVLOG(1) << __func__ << "() operation:" << operation | 378 DVLOG(1) << __func__ << "() operation:" << operation |
| 378 << " os_error:" << os_error | 379 << " os_error:" << os_error |
| 379 << " reason:" << DownloadInterruptReasonToString(reason); | 380 << " reason:" << DownloadInterruptReasonToString(reason); |
| 380 bound_net_log_.AddEvent( | 381 bound_net_log_.AddEvent( |
| 381 net::NetLog::TYPE_DOWNLOAD_FILE_ERROR, | 382 net::NetLogEventType::DOWNLOAD_FILE_ERROR, |
| 382 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); | 383 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); |
| 383 return reason; | 384 return reason; |
| 384 } | 385 } |
| 385 | 386 |
| 386 } // namespace content | 387 } // namespace content |
| OLD | NEW |