Chromium Code Reviews| 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 | 25 |
| 26 namespace content { | 26 namespace content { |
| 27 | 27 |
| 28 // This will initialize the entire array to zero. | 28 BaseFile::BaseFile(const net::BoundNetLog& bound_net_log) |
| 29 const unsigned char BaseFile::kEmptySha256Hash[] = { 0 }; | 29 : bound_net_log_(bound_net_log) {} |
| 30 | |
| 31 BaseFile::BaseFile(const base::FilePath& full_path, | |
| 32 const GURL& source_url, | |
| 33 const GURL& referrer_url, | |
| 34 int64_t received_bytes, | |
| 35 bool calculate_hash, | |
| 36 const std::string& hash_state_bytes, | |
| 37 base::File file, | |
| 38 const net::BoundNetLog& bound_net_log) | |
| 39 : full_path_(full_path), | |
| 40 source_url_(source_url), | |
| 41 referrer_url_(referrer_url), | |
| 42 file_(std::move(file)), | |
| 43 bytes_so_far_(received_bytes), | |
| 44 start_tick_(base::TimeTicks::Now()), | |
| 45 calculate_hash_(calculate_hash), | |
| 46 detached_(false), | |
| 47 bound_net_log_(bound_net_log) { | |
| 48 memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length); | |
| 49 if (calculate_hash_) { | |
| 50 secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | |
| 51 if ((bytes_so_far_ > 0) && // Not starting at the beginning. | |
| 52 (!IsEmptyHash(hash_state_bytes))) { | |
| 53 base::Pickle hash_state(hash_state_bytes.c_str(), | |
| 54 hash_state_bytes.size()); | |
| 55 base::PickleIterator data_iterator(hash_state); | |
| 56 secure_hash_->Deserialize(&data_iterator); | |
| 57 } | |
| 58 } | |
| 59 } | |
| 60 | 30 |
| 61 BaseFile::~BaseFile() { | 31 BaseFile::~BaseFile() { |
| 62 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 32 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 63 if (detached_) | 33 if (detached_) |
| 64 Close(); | 34 Close(); |
| 65 else | 35 else |
| 66 Cancel(); // Will delete the file. | 36 Cancel(); // Will delete the file. |
| 67 } | 37 } |
| 68 | 38 |
| 69 DownloadInterruptReason BaseFile::Initialize( | 39 DownloadInterruptReason BaseFile::Initialize( |
| 70 const base::FilePath& default_directory) { | 40 const base::FilePath& full_path, |
| 41 const base::FilePath& default_directory, | |
| 42 base::File file, | |
| 43 int64_t bytes_so_far, | |
| 44 const std::string& hash_so_far, | |
| 45 scoped_ptr<crypto::SecureHash> hash_state) { | |
| 71 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 46 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 72 DCHECK(!detached_); | 47 DCHECK(!detached_); |
| 73 | 48 |
| 74 if (full_path_.empty()) { | 49 if (full_path.empty()) { |
| 75 base::FilePath initial_directory(default_directory); | 50 base::FilePath initial_directory(default_directory); |
| 76 base::FilePath temp_file; | 51 base::FilePath temp_file; |
| 77 if (initial_directory.empty()) { | 52 if (initial_directory.empty()) { |
| 78 initial_directory = | 53 initial_directory = |
| 79 GetContentClient()->browser()->GetDefaultDownloadDirectory(); | 54 GetContentClient()->browser()->GetDefaultDownloadDirectory(); |
| 80 } | 55 } |
| 81 // |initial_directory| can still be empty if ContentBrowserClient returned | 56 // |initial_directory| can still be empty if ContentBrowserClient returned |
| 82 // an empty path for the downloads directory. | 57 // an empty path for the downloads directory. |
| 83 if ((initial_directory.empty() || | 58 if ((initial_directory.empty() || |
| 84 !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) && | 59 !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) && |
| 85 !base::CreateTemporaryFile(&temp_file)) { | 60 !base::CreateTemporaryFile(&temp_file)) { |
| 86 return LogInterruptReason("Unable to create", 0, | 61 return LogInterruptReason("Unable to create", 0, |
| 87 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 62 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 88 } | 63 } |
| 89 full_path_ = temp_file; | 64 full_path_ = temp_file; |
| 65 } else { | |
| 66 full_path_ = full_path; | |
| 90 } | 67 } |
| 91 | 68 |
| 92 return Open(); | 69 bytes_so_far_ = bytes_so_far; |
| 70 secure_hash_ = std::move(hash_state); | |
| 71 file_ = std::move(file); | |
| 72 | |
| 73 return Open(hash_so_far); | |
| 93 } | 74 } |
| 94 | 75 |
| 95 DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, | 76 DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, |
| 96 size_t data_len) { | 77 size_t data_len) { |
| 97 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 78 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 98 DCHECK(!detached_); | 79 DCHECK(!detached_); |
| 99 | 80 |
| 100 // NOTE(benwells): The above DCHECK won't be present in release builds, | 81 // NOTE(benwells): The above DCHECK won't be present in release builds, |
| 101 // so we log any occurences to see how common this error is in the wild. | 82 // so we log any occurences to see how common this error is in the wild. |
| 102 if (detached_) | 83 if (detached_) |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 127 size_t write_size = static_cast<size_t>(write_result); | 108 size_t write_size = static_cast<size_t>(write_result); |
| 128 DCHECK_LE(write_size, len); | 109 DCHECK_LE(write_size, len); |
| 129 len -= write_size; | 110 len -= write_size; |
| 130 current_data += write_size; | 111 current_data += write_size; |
| 131 bytes_so_far_ += write_size; | 112 bytes_so_far_ += write_size; |
| 132 } | 113 } |
| 133 | 114 |
| 134 RecordDownloadWriteSize(data_len); | 115 RecordDownloadWriteSize(data_len); |
| 135 RecordDownloadWriteLoopCount(write_count); | 116 RecordDownloadWriteLoopCount(write_count); |
| 136 | 117 |
| 137 if (calculate_hash_) | 118 if (secure_hash_) |
| 138 secure_hash_->Update(data, data_len); | 119 secure_hash_->Update(data, data_len); |
| 139 | 120 |
| 140 return DOWNLOAD_INTERRUPT_REASON_NONE; | 121 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 141 } | 122 } |
| 142 | 123 |
| 143 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { | 124 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { |
| 144 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 125 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 145 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 126 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 146 | 127 |
| 147 // If the new path is same as the old one, there is no need to perform the | 128 // If the new path is same as the old one, there is no need to perform the |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 163 // permissions / security descriptors that makes sense in the new directory. | 144 // permissions / security descriptors that makes sense in the new directory. |
| 164 rename_result = MoveFileAndAdjustPermissions(new_path); | 145 rename_result = MoveFileAndAdjustPermissions(new_path); |
| 165 | 146 |
| 166 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) | 147 if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) |
| 167 full_path_ = new_path; | 148 full_path_ = new_path; |
| 168 | 149 |
| 169 // Re-open the file if we were still using it regardless of the interrupt | 150 // Re-open the file if we were still using it regardless of the interrupt |
| 170 // reason. | 151 // reason. |
| 171 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; | 152 DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 172 if (was_in_progress) | 153 if (was_in_progress) |
| 173 open_result = Open(); | 154 open_result = Open(std::string()); |
| 174 | 155 |
| 175 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED); | 156 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED); |
| 176 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result | 157 return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result |
| 177 : rename_result; | 158 : rename_result; |
| 178 } | 159 } |
| 179 | 160 |
| 180 void BaseFile::Detach() { | 161 void BaseFile::Detach() { |
| 181 detached_ = true; | 162 detached_ = true; |
| 182 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DETACHED); | 163 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DETACHED); |
| 183 } | 164 } |
| 184 | 165 |
| 185 void BaseFile::Cancel() { | 166 void BaseFile::Cancel() { |
| 186 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 167 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 187 DCHECK(!detached_); | 168 DCHECK(!detached_); |
| 188 | 169 |
| 189 bound_net_log_.AddEvent(net::NetLog::TYPE_CANCELLED); | 170 bound_net_log_.AddEvent(net::NetLog::TYPE_CANCELLED); |
| 190 | 171 |
| 191 Close(); | 172 Close(); |
| 192 | 173 |
| 193 if (!full_path_.empty()) { | 174 if (!full_path_.empty()) { |
| 194 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DELETED); | 175 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DELETED); |
| 195 base::DeleteFile(full_path_, false); | 176 base::DeleteFile(full_path_, false); |
| 196 } | 177 } |
| 197 | 178 |
| 198 Detach(); | 179 Detach(); |
| 199 } | 180 } |
| 200 | 181 |
| 201 void BaseFile::Finish() { | 182 scoped_ptr<crypto::SecureHash> BaseFile::Finish() { |
| 202 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 203 | |
| 204 if (calculate_hash_) | |
| 205 secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length); | |
| 206 Close(); | |
| 207 } | |
| 208 | |
| 209 void BaseFile::FinishWithError() { | |
| 210 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 183 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 211 Close(); | 184 Close(); |
| 212 } | 185 return std::move(secure_hash_); |
| 213 | |
| 214 void BaseFile::SetClientGuid(const std::string& guid) { | |
| 215 client_guid_ = guid; | |
| 216 } | 186 } |
| 217 | 187 |
| 218 // OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations. | 188 // OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations. |
| 219 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX) | 189 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX) |
| 220 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() { | 190 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( |
| 191 const std::string& client_guid, | |
| 192 const GURL& source_url, | |
| 193 const GURL& referrer_url) { | |
| 221 return DOWNLOAD_INTERRUPT_REASON_NONE; | 194 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 222 } | 195 } |
| 223 #endif | 196 #endif |
| 224 | 197 |
| 225 bool BaseFile::GetHash(std::string* hash) { | 198 std::string BaseFile::DebugString() const { |
| 226 DCHECK(!detached_); | 199 return base::StringPrintf( |
| 227 hash->assign(reinterpret_cast<const char*>(sha256_hash_), | 200 "{ " |
| 228 sizeof(sha256_hash_)); | 201 " full_path_ = \"%" PRFilePath |
| 229 return (calculate_hash_ && !in_progress()); | 202 "\"" |
| 203 " bytes_so_far_ = %" PRId64 " detached_ = %c }", | |
| 204 full_path_.value().c_str(), bytes_so_far_, detached_ ? 'T' : 'F'); | |
| 230 } | 205 } |
| 231 | 206 |
| 232 std::string BaseFile::GetHashState() { | 207 DownloadInterruptReason BaseFile::CalculatePartialHash( |
| 233 if (!calculate_hash_) | 208 const std::string& hash_to_expect) { |
| 234 return std::string(); | 209 secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
| 235 | 210 |
| 236 base::Pickle hash_state; | 211 if (bytes_so_far_ == 0) |
| 237 if (!secure_hash_->Serialize(&hash_state)) | 212 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 238 return std::string(); | |
| 239 | 213 |
| 240 return std::string(reinterpret_cast<const char*>(hash_state.data()), | 214 if (file_.Seek(base::File::FROM_BEGIN, 0) != 0) |
| 241 hash_state.size()); | 215 return LogSystemError("Seek partial file", |
| 216 logging::GetLastSystemErrorCode()); | |
| 217 | |
| 218 const size_t kMinBufferSize = secure_hash_->GetHashLength(); | |
| 219 const size_t kMaxBufferSize = 1024 * 512; | |
| 220 | |
| 221 // The size of the buffer is: | |
| 222 // - at least kMinBufferSize so that we can use it to hold the hash as well. | |
| 223 // - at most kMaxBufferSize so that there's a reasonable bound. | |
| 224 // - not larger than |bytes_so_far_| unless bytes_so_far_ is less than the | |
| 225 // hash size. | |
| 226 std::vector<char> buffer(std::max( | |
| 227 kMinBufferSize, std::min<size_t>(kMaxBufferSize, bytes_so_far_))); | |
| 228 | |
| 229 int64_t current_position = 0; | |
| 230 while (current_position < bytes_so_far_) { | |
| 231 int length = file_.ReadAtCurrentPos(&buffer.front(), buffer.size()); | |
| 232 if (length == -1) { | |
| 233 return LogInterruptReason("Reading partial file", | |
| 234 logging::GetLastSystemErrorCode(), | |
| 235 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); | |
| 236 } | |
| 237 | |
| 238 if (length == 0) | |
| 239 break; | |
| 240 | |
| 241 secure_hash_->Update(&buffer.front(), length); | |
| 242 current_position += length; | |
| 243 } | |
| 244 | |
| 245 if (current_position != bytes_so_far_) { | |
| 246 return LogInterruptReason("Verifying prefix hash", 0, | |
| 247 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); | |
| 248 } | |
| 249 | |
| 250 if (!hash_to_expect.empty()) { | |
| 251 DCHECK_EQ(secure_hash_->GetHashLength(), hash_to_expect.size()); | |
| 252 DCHECK(buffer.size() >= secure_hash_->GetHashLength()); | |
| 253 scoped_ptr<crypto::SecureHash> partial_hash(secure_hash_->Clone()); | |
| 254 partial_hash->Finish(&buffer.front(), buffer.size()); | |
| 255 | |
| 256 if (memcmp(&buffer.front(), hash_to_expect.c_str(), | |
| 257 partial_hash->GetHashLength())) { | |
| 258 return LogInterruptReason("Verifying prefix hash", 0, | |
| 259 DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 return DOWNLOAD_INTERRUPT_REASON_NONE; | |
| 242 } | 264 } |
| 243 | 265 |
| 244 // static | 266 DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) { |
| 245 bool BaseFile::IsEmptyHash(const std::string& hash) { | |
| 246 return (hash.size() == crypto::kSHA256Length && | |
| 247 0 == memcmp(hash.data(), kEmptySha256Hash, crypto::kSHA256Length)); | |
| 248 } | |
| 249 | |
| 250 std::string BaseFile::DebugString() const { | |
| 251 return base::StringPrintf("{ source_url_ = \"%s\"" | |
| 252 " full_path_ = \"%" PRFilePath "\"" | |
| 253 " bytes_so_far_ = %" PRId64 | |
| 254 " detached_ = %c }", | |
| 255 source_url_.spec().c_str(), | |
| 256 full_path_.value().c_str(), | |
| 257 bytes_so_far_, | |
| 258 detached_ ? 'T' : 'F'); | |
| 259 } | |
| 260 | |
| 261 DownloadInterruptReason BaseFile::Open() { | |
| 262 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 267 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 263 DCHECK(!detached_); | 268 DCHECK(!detached_); |
| 264 DCHECK(!full_path_.empty()); | 269 DCHECK(!full_path_.empty()); |
| 265 | 270 |
| 271 // Create a new file if it is not provided. | |
| 272 if (!file_.IsValid()) { | |
| 273 file_.Initialize(full_path_, base::File::FLAG_OPEN_ALWAYS | | |
| 274 base::File::FLAG_WRITE | | |
| 275 base::File::FLAG_READ); | |
| 276 if (!file_.IsValid()) { | |
| 277 return LogNetError("Open/Initialize File", | |
| 278 net::FileErrorToNetError(file_.error_details())); | |
| 279 } | |
| 280 } | |
| 281 | |
| 266 bound_net_log_.BeginEvent( | 282 bound_net_log_.BeginEvent( |
| 267 net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, | 283 net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, |
| 268 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); | 284 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); |
| 269 | 285 |
| 270 // Create a new file if it is not provided. | 286 if (!secure_hash_) { |
|
svaldez
2016/03/09 19:27:33
|| secure_hash_.empty()? (Might not be necessaru)
asanka
2016/03/10 16:48:08
secure_hash_ is a scoped_ptr<crypto::SecureHash>.
| |
| 271 if (!file_.IsValid()) { | 287 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); |
| 272 file_.Initialize( | 288 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 273 full_path_, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE); | 289 ClearFile(); |
| 274 if (!file_.IsValid()) { | 290 return reason; |
| 275 return LogNetError("Open", | |
| 276 net::FileErrorToNetError(file_.error_details())); | |
| 277 } | 291 } |
| 278 } | 292 } |
| 279 | 293 |
| 280 // We may be re-opening the file after rename. Always make sure we're | |
| 281 // writing at the end of the file. | |
| 282 int64_t file_size = file_.Seek(base::File::FROM_END, 0); | 294 int64_t file_size = file_.Seek(base::File::FROM_END, 0); |
| 283 if (file_size < 0) { | 295 if (file_size < 0) { |
| 284 logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); | 296 logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); |
| 285 ClearFile(); | 297 ClearFile(); |
| 286 return LogSystemError("Seek", error); | 298 return LogSystemError("Seeking to end", error); |
| 287 } else if (file_size > bytes_so_far_) { | 299 } else if (file_size > bytes_so_far_) { |
| 288 // The file is larger than we expected. | 300 // The file is larger than we expected. |
| 289 // This is OK, as long as we don't use the extra. | 301 // This is OK, as long as we don't use the extra. |
| 290 // Truncate the file. | 302 // Truncate the file. |
| 291 if (!file_.SetLength(bytes_so_far_) || | 303 if (!file_.SetLength(bytes_so_far_) || |
| 292 file_.Seek(base::File::FROM_BEGIN, bytes_so_far_) != bytes_so_far_) { | 304 file_.Seek(base::File::FROM_BEGIN, bytes_so_far_) != bytes_so_far_) { |
| 293 logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); | 305 logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); |
| 294 ClearFile(); | 306 ClearFile(); |
| 295 return LogSystemError("Truncate", error); | 307 return LogSystemError("Truncating to last known offset", error); |
| 296 } | 308 } |
| 297 } else if (file_size < bytes_so_far_) { | 309 } else if (file_size < bytes_so_far_) { |
| 298 // The file is shorter than we expected. Our hashes won't be valid. | 310 // The file is shorter than we expected. Our hashes won't be valid. |
| 299 ClearFile(); | 311 ClearFile(); |
| 300 return LogInterruptReason("Unable to seek to last written point", 0, | 312 return LogInterruptReason("Unable to seek to last written point", 0, |
| 301 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); | 313 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); |
| 302 } | 314 } |
| 303 | 315 |
| 304 return DOWNLOAD_INTERRUPT_REASON_NONE; | 316 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 305 } | 317 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 base::File::Error file_error = base::File::OSErrorToFileError(os_error); | 352 base::File::Error file_error = base::File::OSErrorToFileError(os_error); |
| 341 return LogInterruptReason( | 353 return LogInterruptReason( |
| 342 operation, os_error, | 354 operation, os_error, |
| 343 ConvertFileErrorToInterruptReason(file_error)); | 355 ConvertFileErrorToInterruptReason(file_error)); |
| 344 } | 356 } |
| 345 | 357 |
| 346 DownloadInterruptReason BaseFile::LogInterruptReason( | 358 DownloadInterruptReason BaseFile::LogInterruptReason( |
| 347 const char* operation, | 359 const char* operation, |
| 348 int os_error, | 360 int os_error, |
| 349 DownloadInterruptReason reason) { | 361 DownloadInterruptReason reason) { |
| 362 DVLOG(1) << __FUNCTION__ << "() operation:" << operation | |
| 363 << " os_error:" << os_error | |
| 364 << " reason:" << DownloadInterruptReasonToString(reason); | |
| 350 bound_net_log_.AddEvent( | 365 bound_net_log_.AddEvent( |
| 351 net::NetLog::TYPE_DOWNLOAD_FILE_ERROR, | 366 net::NetLog::TYPE_DOWNLOAD_FILE_ERROR, |
| 352 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); | 367 base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason)); |
| 353 return reason; | 368 return reason; |
| 354 } | 369 } |
| 355 | 370 |
| 356 } // namespace content | 371 } // namespace content |
| OLD | NEW |