This source file includes following definitions.
- MapShFileOperationCodes
- MapScanAndSaveErrorCodeToInterruptReason
- MoveFileAndAdjustPermissions
- AnnotateWithSourceInformation
#include "content/browser/download/base_file.h"
#include <windows.h>
#include <cguid.h>
#include <objbase.h>
#include <shellapi.h>
#include "base/file_util.h"
#include "base/guid.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_stats.h"
#include "content/browser/safe_util_win.h"
#include "content/public/browser/browser_thread.h"
namespace content {
namespace {
const int kAllSpecialShFileOperationCodes[] = {
ERROR_ACCESS_DENIED,
0x71,
0x72,
0x73,
0x74,
0x75,
0x76,
0x78,
0x79,
0x7A,
0x7C,
0x7D,
0x7E,
0x80,
0x81,
0x82,
0x83,
0x84,
0x85,
0x86,
0x87,
0x88,
0xB7,
0x402,
0x10000,
0x10074,
};
DownloadInterruptReason MapShFileOperationCodes(int code) {
DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
switch (code) {
case ERROR_ACCESS_DENIED:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x71:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x75:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x78:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x79:
result = DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
break;
case 0x7C:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x7E:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x80:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x81:
result = DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
break;
case 0x82:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x83:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x84:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x85:
result = DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE;
break;
case 0x86:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x87:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0x88:
result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
break;
case 0xB7:
result = DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
break;
case 0x10000:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x72:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x73:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x74:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x76:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x7A:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x7D:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x402:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
case 0x10074:
result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
break;
}
if (result == DOWNLOAD_INTERRUPT_REASON_FILE_FAILED) {
UMA_HISTOGRAM_CUSTOM_ENUMERATION(
"Download.MapWinShErrorFileFailed", code,
base::CustomHistogram::ArrayToCustomRanges(
kAllSpecialShFileOperationCodes,
arraysize(kAllSpecialShFileOperationCodes)));
}
if (result == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) {
UMA_HISTOGRAM_CUSTOM_ENUMERATION(
"Download.MapWinShErrorAccessDenied", code,
base::CustomHistogram::ArrayToCustomRanges(
kAllSpecialShFileOperationCodes,
arraysize(kAllSpecialShFileOperationCodes)));
}
if (result != DOWNLOAD_INTERRUPT_REASON_NONE)
return result;
return ConvertNetErrorToInterruptReason(
net::MapSystemError(code), DOWNLOAD_INTERRUPT_FROM_DISK);
}
DownloadInterruptReason MapScanAndSaveErrorCodeToInterruptReason(
HRESULT result) {
if (SUCCEEDED(result))
return DOWNLOAD_INTERRUPT_REASON_NONE;
switch (result) {
case INET_E_SECURITY_PROBLEM:
return DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED;
case E_FAIL:
return DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED;
default:
return DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED;
}
}
}
DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
const base::FilePath& new_path) {
base::ThreadRestrictions::AssertIOAllowed();
base::FilePath::StringType source = full_path_.value();
base::FilePath::StringType target = new_path.value();
source.append(1, L'\0');
target.append(1, L'\0');
SHFILEOPSTRUCT move_info = {0};
move_info.wFunc = FO_MOVE;
move_info.pFrom = source.c_str();
move_info.pTo = target.c_str();
move_info.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI |
FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS;
int result = SHFileOperation(&move_info);
DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE;
if (result == 0 && move_info.fAnyOperationsAborted)
interrupt_reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
else if (result != 0)
interrupt_reason = MapShFileOperationCodes(result);
if (interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE)
return LogInterruptReason("SHFileOperation", result, interrupt_reason);
return interrupt_reason;
}
DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
DCHECK(!detached_);
bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
std::string braces_guid = "{" + client_guid_ + "}";
GUID guid = GUID_NULL;
if (base::IsValidGUID(client_guid_)) {
HRESULT hr = CLSIDFromString(
base::UTF8ToUTF16(braces_guid).c_str(), &guid);
if (FAILED(hr))
guid = GUID_NULL;
}
HRESULT hr = AVScanFile(full_path_, source_url_.spec(), guid);
if (!base::PathExists(full_path_)) {
DCHECK(FAILED(hr));
result = MapScanAndSaveErrorCodeToInterruptReason(hr);
if (result == DOWNLOAD_INTERRUPT_REASON_NONE) {
RecordDownloadCount(FILE_MISSING_AFTER_SUCCESSFUL_SCAN_COUNT);
result = DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED;
}
LogInterruptReason("ScanAndSaveDownloadedFile", hr, result);
}
bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
return result;
}
}