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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS; | 189 FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS; |
| 190 | 190 |
| 191 int result = SHFileOperation(&move_info); | 191 int result = SHFileOperation(&move_info); |
| 192 | 192 |
| 193 if (result == 0) | 193 if (result == 0) |
| 194 return (move_info.fAnyOperationsAborted) ? net::ERR_ABORTED : net::OK; | 194 return (move_info.fAnyOperationsAborted) ? net::ERR_ABORTED : net::OK; |
| 195 | 195 |
| 196 return MapShFileOperationCodes(result); | 196 return MapShFileOperationCodes(result); |
| 197 } | 197 } |
| 198 | 198 |
| 199 // Maps a return code from ScanAndSaveDownloadedFile() to a net::Error. The | |
| 200 // return code is usually from the final IAttachmentExecute::Save() call. | |
| 201 net::Error MapScanAndSaveErrorCodeToNetError(HRESULT hresult) { | |
| 202 switch (hresult) { | |
| 203 case INET_E_SECURITY_PROBLEM: // 0x800c000e | |
| 204 // This is returned if the download was blocked due to security | |
| 205 // restrictions. E.g. if the source URL was in the Restricted Sites zone | |
| 206 // and downloads are blocked on that zone, then the download would be | |
| 207 // deleted and this error code is returned. | |
| 208 return net::ERR_BLOCKED_BY_CLIENT; | |
| 209 | |
| 210 case __HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED): // 0x80070005 | |
| 211 case __HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT): // 0x800700c1 | |
| 212 // These are errors that we have observed in the wild | |
| 213 // (http://crbug.com/153212). We don't have a useful explanation as to why | |
| 214 // this happens. | |
|
Randy Smith (Not in Mondays)
2012/10/16 18:19:19
Part of me would like to find *some* different err
asanka
2012/10/25 23:51:27
Added a new interrupt reason. I named it 'SECURITY
| |
| 215 case E_FAIL: // 0x80004005 | |
| 216 // Returned if an anti-virus product reports an infection in the | |
| 217 // downloaded file during IAE::Save(). | |
| 218 default: | |
| 219 // Any error that occurs during IAttachmentExecute::Save() other than | |
| 220 // INET_E_SECURITY_PROBLEM is interpreted as a virus infection. This | |
| 221 // follows the behavior in IE. | |
| 222 return net::ERR_FILE_VIRUS_INFECTED; | |
| 223 } | |
| 224 } | |
| 225 | |
| 199 #endif | 226 #endif |
| 200 | 227 |
| 201 } // namespace | 228 } // namespace |
| 202 | 229 |
| 203 // This will initialize the entire array to zero. | 230 // This will initialize the entire array to zero. |
| 204 const unsigned char BaseFile::kEmptySha256Hash[] = { 0 }; | 231 const unsigned char BaseFile::kEmptySha256Hash[] = { 0 }; |
| 205 | 232 |
| 206 BaseFile::BaseFile(const FilePath& full_path, | 233 BaseFile::BaseFile(const FilePath& full_path, |
| 207 const GURL& source_url, | 234 const GURL& source_url, |
| 208 const GURL& referrer_url, | 235 const GURL& referrer_url, |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 PickleIterator data_iterator(hash_state); | 484 PickleIterator data_iterator(hash_state); |
| 458 | 485 |
| 459 return secure_hash_->Deserialize(&data_iterator); | 486 return secure_hash_->Deserialize(&data_iterator); |
| 460 } | 487 } |
| 461 | 488 |
| 462 bool BaseFile::IsEmptyHash(const std::string& hash) { | 489 bool BaseFile::IsEmptyHash(const std::string& hash) { |
| 463 return (hash.size() == kSha256HashLen && | 490 return (hash.size() == kSha256HashLen && |
| 464 0 == memcmp(hash.data(), kEmptySha256Hash, sizeof(kSha256HashLen))); | 491 0 == memcmp(hash.data(), kEmptySha256Hash, sizeof(kSha256HashLen))); |
| 465 } | 492 } |
| 466 | 493 |
| 467 void BaseFile::AnnotateWithSourceInformation() { | 494 net::Error BaseFile::AnnotateWithSourceInformation() { |
| 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 495 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 469 DCHECK(!detached_); | 496 DCHECK(!detached_); |
| 470 | 497 |
| 498 bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED); | |
| 499 int os_error = 0; // Only used for logging. | |
| 500 net::Error net_error = net::OK; | |
| 471 #if defined(OS_WIN) | 501 #if defined(OS_WIN) |
| 472 // Sets the Zone to tell Windows that this file comes from the internet. | 502 HRESULT hr = win_util::ScanAndSaveDownloadedFile(full_path_, source_url_); |
| 473 // We ignore the return value because a failure is not fatal. | 503 if (!file_util::PathExists(full_path_)) { |
| 474 win_util::SetInternetZoneIdentifier(full_path_, | 504 DCHECK(FAILED(hr)); |
| 475 UTF8ToWide(source_url_.spec())); | 505 // If the ScanAndSaveDownloadedFile() call failed, but the downloaded file |
| 506 // is still around, then log the error, but don't show it to the | |
| 507 // user. Attachment Execution Services deletes the submitted file if the | |
| 508 // downloaded file is blocked by policy or if it was found to be infected. | |
| 509 // | |
| 510 // If the file is still there, then the error could be due to AES not being | |
| 511 // available or some other error during the AES invocation. In either case, | |
| 512 // we don't surface the error to the user. | |
| 513 net_error = MapScanAndSaveErrorCodeToNetError(hr); | |
| 514 if (net_error == net::OK) | |
| 515 net_error = net::ERR_FAILED; | |
|
Randy Smith (Not in Mondays)
2012/10/16 18:19:19
Do we want some better way to call out the case in
asanka
2012/10/25 23:51:27
Add a UMA count for this case.
| |
| 516 } | |
| 517 os_error = hr; | |
| 476 #elif defined(OS_MACOSX) | 518 #elif defined(OS_MACOSX) |
| 477 content::AddQuarantineMetadataToFile(full_path_, source_url_, referrer_url_); | 519 content::AddQuarantineMetadataToFile(full_path_, source_url_, referrer_url_); |
| 478 content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_); | 520 content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_); |
| 479 #elif defined(OS_LINUX) | 521 #elif defined(OS_LINUX) |
| 480 content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_); | 522 content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_); |
| 481 #endif | 523 #endif |
| 524 bound_net_log_.EndEvent( | |
| 525 net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED, | |
| 526 base::Bind(&download_net_logs::AnnotateWithSourceCallback, | |
| 527 os_error, net_error)); | |
| 528 return net_error; | |
| 482 } | 529 } |
| 483 | 530 |
| 484 void BaseFile::CreateFileStream() { | 531 void BaseFile::CreateFileStream() { |
| 485 file_stream_.reset(new net::FileStream(bound_net_log_.net_log())); | 532 file_stream_.reset(new net::FileStream(bound_net_log_.net_log())); |
| 486 file_stream_->SetBoundNetLogSource(bound_net_log_); | 533 file_stream_->SetBoundNetLogSource(bound_net_log_); |
| 487 } | 534 } |
| 488 | 535 |
| 489 net::Error BaseFile::Open() { | 536 net::Error BaseFile::Open() { |
| 490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 537 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 491 DCHECK(!detached_); | 538 DCHECK(!detached_); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const { | 603 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const { |
| 557 base::TimeDelta diff = current_time - start_tick_; | 604 base::TimeDelta diff = current_time - start_tick_; |
| 558 int64 diff_ms = diff.InMilliseconds(); | 605 int64 diff_ms = diff.InMilliseconds(); |
| 559 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms; | 606 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms; |
| 560 } | 607 } |
| 561 | 608 |
| 562 int64 BaseFile::CurrentSpeed() const { | 609 int64 BaseFile::CurrentSpeed() const { |
| 563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 610 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 564 return CurrentSpeedAtTime(base::TimeTicks::Now()); | 611 return CurrentSpeedAtTime(base::TimeTicks::Now()); |
| 565 } | 612 } |
| OLD | NEW |