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 |