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 |