| Index: content/browser/download/base_file_win.cc
|
| diff --git a/content/browser/download/base_file_win.cc b/content/browser/download/base_file_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b3b7e182bb63bf4165107a9cdb6d72566955c855
|
| --- /dev/null
|
| +++ b/content/browser/download/base_file_win.cc
|
| @@ -0,0 +1,189 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/download/base_file.h"
|
| +
|
| +#include <windows.h>
|
| +#include <shellapi.h>
|
| +
|
| +#include "base/threading/thread_restrictions.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "content/browser/download/download_interrupt_reasons_impl.h"
|
| +#include "content/browser/safe_util_win.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +
|
| +namespace {
|
| +
|
| +// Maps the result of a call to |SHFileOperation()| onto a
|
| +// |content::DownloadInterruptReason|.
|
| +//
|
| +// These return codes are *old* (as in, DOS era), and specific to
|
| +// |SHFileOperation()|.
|
| +// They do not appear in any windows header.
|
| +//
|
| +// See http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx.
|
| +content::DownloadInterruptReason MapShFileOperationCodes(int code) {
|
| + // Check these pre-Win32 error codes first, then check for matches
|
| + // in Winerror.h.
|
| +
|
| + switch (code) {
|
| + // The source and destination files are the same file.
|
| + // DE_SAMEFILE == 0x71
|
| + case 0x71: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The operation was canceled by the user, or silently canceled if the
|
| + // appropriate flags were supplied to SHFileOperation.
|
| + // DE_OPCANCELLED == 0x75
|
| + case 0x75: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // Security settings denied access to the source.
|
| + // DE_ACCESSDENIEDSRC == 0x78
|
| + case 0x78: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The source or destination path exceeded or would exceed MAX_PATH.
|
| + // DE_PATHTOODEEP == 0x79
|
| + case 0x79: return content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
|
| +
|
| + // The path in the source or destination or both was invalid.
|
| + // DE_INVALIDFILES == 0x7C
|
| + case 0x7C: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The destination path is an existing file.
|
| + // DE_FLDDESTISFILE == 0x7E
|
| + case 0x7E: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The destination path is an existing folder.
|
| + // DE_FILEDESTISFLD == 0x80
|
| + case 0x80: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The name of the file exceeds MAX_PATH.
|
| + // DE_FILENAMETOOLONG == 0x81
|
| + case 0x81: return content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
|
| +
|
| + // The destination is a read-only CD-ROM, possibly unformatted.
|
| + // DE_DEST_IS_CDROM == 0x82
|
| + case 0x82: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The destination is a read-only DVD, possibly unformatted.
|
| + // DE_DEST_IS_DVD == 0x83
|
| + case 0x83: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The destination is a writable CD-ROM, possibly unformatted.
|
| + // DE_DEST_IS_CDRECORD == 0x84
|
| + case 0x84: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The file involved in the operation is too large for the destination
|
| + // media or file system.
|
| + // DE_FILE_TOO_LARGE == 0x85
|
| + case 0x85: return content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE;
|
| +
|
| + // The source is a read-only CD-ROM, possibly unformatted.
|
| + // DE_SRC_IS_CDROM == 0x86
|
| + case 0x86: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The source is a read-only DVD, possibly unformatted.
|
| + // DE_SRC_IS_DVD == 0x87
|
| + case 0x87: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // The source is a writable CD-ROM, possibly unformatted.
|
| + // DE_SRC_IS_CDRECORD == 0x88
|
| + case 0x88: return content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
|
| +
|
| + // MAX_PATH was exceeded during the operation.
|
| + // DE_ERROR_MAX == 0xB7
|
| + case 0xB7: return content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG;
|
| +
|
| + // An unspecified error occurred on the destination.
|
| + // XE_ERRORONDEST == 0x10000
|
| + case 0x10000: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // Multiple file paths were specified in the source buffer, but only one
|
| + // destination file path.
|
| + // DE_MANYSRC1DEST == 0x72
|
| + case 0x72: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // Rename operation was specified but the destination path is
|
| + // a different directory. Use the move operation instead.
|
| + // DE_DIFFDIR == 0x73
|
| + case 0x73: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The source is a root directory, which cannot be moved or renamed.
|
| + // DE_ROOTDIR == 0x74
|
| + case 0x74: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The destination is a subtree of the source.
|
| + // DE_DESTSUBTREE == 0x76
|
| + case 0x76: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The operation involved multiple destination paths,
|
| + // which can fail in the case of a move operation.
|
| + // DE_MANYDEST == 0x7A
|
| + case 0x7A: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // The source and destination have the same parent folder.
|
| + // DE_DESTSAMETREE == 0x7D
|
| + case 0x7D: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // An unknown error occurred. This is typically due to an invalid path in
|
| + // the source or destination. This error does not occur on Windows Vista
|
| + // and later.
|
| + // DE_UNKNOWN_ERROR == 0x402
|
| + case 0x402: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| +
|
| + // Destination is a root directory and cannot be renamed.
|
| + // DE_ROOTDIR | ERRORONDEST == 0x10074
|
| + case 0x10074: return content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| + }
|
| +
|
| + // If not one of the above codes, it should be a standard Windows error code.
|
| + return content::ConvertNetErrorToInterruptReason(
|
| + net::MapSystemError(code), content::DOWNLOAD_INTERRUPT_FROM_DISK);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// Renames a file using the SHFileOperation API to ensure that the target file
|
| +// gets the correct default security descriptor in the new path.
|
| +// Returns a network error, or net::OK for success.
|
| +content::DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
|
| + const FilePath& new_path) {
|
| + base::ThreadRestrictions::AssertIOAllowed();
|
| +
|
| + // The parameters to SHFileOperation must be terminated with 2 NULL chars.
|
| + FilePath::StringType source = full_path_.value();
|
| + 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);
|
| + content::DownloadInterruptReason interrupt_reason =
|
| + content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
| +
|
| + if (result == 0 && move_info.fAnyOperationsAborted)
|
| + interrupt_reason = content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
|
| + else if (result != 0)
|
| + interrupt_reason = MapShFileOperationCodes(result);
|
| +
|
| + if (interrupt_reason != content::DOWNLOAD_INTERRUPT_REASON_NONE)
|
| + return LogInterruptReason("SHFileOperation", result, interrupt_reason);
|
| + return interrupt_reason;
|
| +}
|
| +
|
| +void BaseFile::AnnotateWithSourceInformation() {
|
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
|
| + DCHECK(!detached_);
|
| +
|
| + // Sets the Zone to tell Windows that this file comes from the internet.
|
| + // We ignore the return value because a failure is not fatal.
|
| + win_util::SetInternetZoneIdentifier(full_path_,
|
| + UTF8ToWide(source_url_.spec()));
|
| +}
|
|
|