| Index: content/browser/download/base_file.cc
|
| diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc
|
| index 6cbe98e3eb0fbf0d3334a6238ecf2d16fadb27f0..65fd7a1991ef5d3ce585985e3b5d33c8656a3c65 100644
|
| --- a/content/browser/download/base_file.cc
|
| +++ b/content/browser/download/base_file.cc
|
| @@ -11,7 +11,7 @@
|
| #include "base/pickle.h"
|
| #include "base/stringprintf.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/download/download_net_log_parameters.h"
|
| #include "content/browser/download/download_stats.h"
|
| #include "content/public/browser/browser_thread.h"
|
| @@ -20,186 +20,8 @@
|
| #include "net/base/file_stream.h"
|
| #include "net/base/net_errors.h"
|
|
|
| -#if defined(OS_WIN)
|
| -#include <windows.h>
|
| -#include <shellapi.h>
|
| -
|
| -#include "content/browser/safe_util_win.h"
|
| -#elif defined(OS_MACOSX)
|
| -#include "content/browser/download/file_metadata_mac.h"
|
| -#elif defined(OS_LINUX)
|
| -#include "content/browser/download/file_metadata_linux.h"
|
| -#endif
|
| -
|
| using content::BrowserThread;
|
|
|
| -namespace {
|
| -
|
| -#define LOG_ERROR(o, e) \
|
| - LogError(__FILE__, __LINE__, __FUNCTION__, bound_net_log_, o, e)
|
| -
|
| -// Logs the value and passes error on through, converting to a |net::Error|.
|
| -// Returns |ERR_UNEXPECTED| if the value is not in the enum.
|
| -net::Error LogError(const char* file,
|
| - int line,
|
| - const char* func,
|
| - const net::BoundNetLog& bound_net_log,
|
| - const char* operation,
|
| - int error) {
|
| - const char* err_string = "";
|
| - net::Error net_error = net::OK;
|
| -
|
| -#define NET_ERROR(label, value) \
|
| - case net::ERR_##label: \
|
| - err_string = #label; \
|
| - net_error = net::ERR_##label; \
|
| - break;
|
| -
|
| - switch (error) {
|
| - case net::OK:
|
| - return net::OK;
|
| -
|
| -#include "net/base/net_error_list.h"
|
| -
|
| - default:
|
| - err_string = "Unexpected enum value";
|
| - net_error = net::ERR_UNEXPECTED;
|
| - break;
|
| - }
|
| -
|
| -#undef NET_ERROR
|
| -
|
| - VLOG(1) << " " << func << "(): " << operation
|
| - << "() returned error " << error << " (" << err_string << ")";
|
| -
|
| - bound_net_log.AddEvent(
|
| - net::NetLog::TYPE_DOWNLOAD_FILE_ERROR,
|
| - base::Bind(&download_net_logs::FileErrorCallback, operation, net_error));
|
| -
|
| - return net_error;
|
| -}
|
| -
|
| -#if defined(OS_WIN)
|
| -
|
| -#define SHFILE_TO_NET_ERROR(symbol, value, mapping, description) \
|
| - case value: return net::ERR_##mapping;
|
| -
|
| -// Maps the result of a call to |SHFileOperation()| onto a |net::Error|.
|
| -//
|
| -// 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.
|
| -net::Error MapShFileOperationCodes(int code) {
|
| - // Check these pre-Win32 error codes first, then check for matches
|
| - // in Winerror.h.
|
| -
|
| - switch (code) {
|
| - // Error Code, Value, Platform Error Mapping, Meaning
|
| - SHFILE_TO_NET_ERROR(DE_SAMEFILE, 0x71, FILE_EXISTS,
|
| - "The source and destination files are the same file.")
|
| - SHFILE_TO_NET_ERROR(DE_OPCANCELLED, 0x75, ABORTED,
|
| - "The operation was canceled by the user, or silently canceled if "
|
| - "the appropriate flags were supplied to SHFileOperation.")
|
| - SHFILE_TO_NET_ERROR(DE_ACCESSDENIEDSRC, 0x78, ACCESS_DENIED,
|
| - "Security settings denied access to the source.")
|
| - SHFILE_TO_NET_ERROR(DE_PATHTOODEEP, 0x79, FILE_PATH_TOO_LONG,
|
| - "The source or destination path exceeded or would exceed MAX_PATH.")
|
| - SHFILE_TO_NET_ERROR(DE_INVALIDFILES, 0x7C, FILE_NOT_FOUND,
|
| - "The path in the source or destination or both was invalid.")
|
| - SHFILE_TO_NET_ERROR(DE_FLDDESTISFILE, 0x7E, FILE_EXISTS,
|
| - "The destination path is an existing file.")
|
| - SHFILE_TO_NET_ERROR(DE_FILEDESTISFLD, 0x80, FILE_EXISTS,
|
| - "The destination path is an existing folder.")
|
| - SHFILE_TO_NET_ERROR(DE_FILENAMETOOLONG, 0x81, FILE_PATH_TOO_LONG,
|
| - "The name of the file exceeds MAX_PATH.")
|
| - SHFILE_TO_NET_ERROR(DE_DEST_IS_CDROM, 0x82, ACCESS_DENIED,
|
| - "The destination is a read-only CD-ROM, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_DEST_IS_DVD, 0x83, ACCESS_DENIED,
|
| - "The destination is a read-only DVD, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_DEST_IS_CDRECORD, 0x84, ACCESS_DENIED,
|
| - "The destination is a writable CD-ROM, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_FILE_TOO_LARGE, 0x85, FILE_TOO_BIG,
|
| - "The file involved in the operation is too large for the destination "
|
| - "media or file system.")
|
| - SHFILE_TO_NET_ERROR(DE_SRC_IS_CDROM, 0x86, ACCESS_DENIED,
|
| - "The source is a read-only CD-ROM, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_SRC_IS_DVD, 0x87, ACCESS_DENIED,
|
| - "The source is a read-only DVD, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_SRC_IS_CDRECORD, 0x88, ACCESS_DENIED,
|
| - "The source is a writable CD-ROM, possibly unformatted.")
|
| - SHFILE_TO_NET_ERROR(DE_ERROR_MAX, 0xB7, FILE_PATH_TOO_LONG,
|
| - "MAX_PATH was exceeded during the operation.")
|
| - SHFILE_TO_NET_ERROR(XE_ERRORONDEST, 0x10000, UNEXPECTED,
|
| - "An unspecified error occurred on the destination.")
|
| -
|
| - // These are not expected to occur for in our usage.
|
| - SHFILE_TO_NET_ERROR(DE_MANYSRC1DEST, 0x72, FAILED,
|
| - "Multiple file paths were specified in the source buffer, "
|
| - "but only one destination file path.")
|
| - SHFILE_TO_NET_ERROR(DE_DIFFDIR, 0x73, FAILED,
|
| - "Rename operation was specified but the destination path is "
|
| - "a different directory. Use the move operation instead.")
|
| - SHFILE_TO_NET_ERROR(DE_ROOTDIR, 0x74, FAILED,
|
| - "The source is a root directory, which cannot be moved or renamed.")
|
| - SHFILE_TO_NET_ERROR(DE_DESTSUBTREE, 0x76, FAILED,
|
| - "The destination is a subtree of the source.")
|
| - SHFILE_TO_NET_ERROR(DE_MANYDEST, 0x7A, FAILED,
|
| - "The operation involved multiple destination paths, "
|
| - "which can fail in the case of a move operation.")
|
| - SHFILE_TO_NET_ERROR(DE_DESTSAMETREE, 0x7D, FAILED,
|
| - "The source and destination have the same parent folder.")
|
| - SHFILE_TO_NET_ERROR(DE_UNKNOWN_ERROR, 0x402, 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.")
|
| - SHFILE_TO_NET_ERROR(DE_ROOTDIR | ERRORONDEST, 0x10074, FAILED,
|
| - "Destination is a root directory and cannot be renamed.")
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - // If not one of the above codes, it should be a standard Windows error code.
|
| - return static_cast<net::Error>(net::MapSystemError(code));
|
| -}
|
| -
|
| -#undef SHFILE_TO_NET_ERROR
|
| -
|
| -// 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.
|
| -net::Error RenameFileAndResetSecurityDescriptor(
|
| - const FilePath& source_file_path,
|
| - const FilePath& target_file_path) {
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| -
|
| - // The parameters to SHFileOperation must be terminated with 2 NULL chars.
|
| - std::wstring source = source_file_path.value();
|
| - std::wstring target = target_file_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);
|
| -
|
| - if (result == 0)
|
| - return (move_info.fAnyOperationsAborted) ? net::ERR_ABORTED : net::OK;
|
| -
|
| - return MapShFileOperationCodes(result);
|
| -}
|
| -
|
| -#endif
|
| -
|
| -} // namespace
|
| -
|
| // This will initialize the entire array to zero.
|
| const unsigned char BaseFile::kEmptySha256Hash[] = { 0 };
|
|
|
| @@ -208,7 +30,7 @@ BaseFile::BaseFile(const FilePath& full_path,
|
| const GURL& referrer_url,
|
| int64 received_bytes,
|
| bool calculate_hash,
|
| - const std::string& hash_state,
|
| + const std::string& hash_state_bytes,
|
| scoped_ptr<net::FileStream> file_stream,
|
| const net::BoundNetLog& bound_net_log)
|
| : full_path_(full_path),
|
| @@ -224,9 +46,10 @@ BaseFile::BaseFile(const FilePath& full_path,
|
| if (calculate_hash_) {
|
| secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
|
| if ((bytes_so_far_ > 0) && // Not starting at the beginning.
|
| - (hash_state != "") && // Reasonably sure we have a hash state.
|
| - (!IsEmptyHash(hash_state))) {
|
| - SetHashState(hash_state);
|
| + (!IsEmptyHash(hash_state_bytes))) {
|
| + Pickle hash_state(hash_state_bytes.c_str(), hash_state_bytes.size());
|
| + PickleIterator data_iterator(hash_state);
|
| + secure_hash_->Deserialize(&data_iterator);
|
| }
|
| }
|
| }
|
| @@ -239,7 +62,8 @@ BaseFile::~BaseFile() {
|
| Cancel(); // Will delete the file.
|
| }
|
|
|
| -net::Error BaseFile::Initialize(const FilePath& default_directory) {
|
| +content::DownloadInterruptReason BaseFile::Initialize(
|
| + const FilePath& default_directory) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| DCHECK(!detached_);
|
|
|
| @@ -260,7 +84,8 @@ net::Error BaseFile::Initialize(const FilePath& default_directory) {
|
| if ((initial_directory.empty() ||
|
| !file_util::CreateTemporaryFileInDir(initial_directory, &temp_file)) &&
|
| !file_util::CreateTemporaryFile(&temp_file)) {
|
| - return LOG_ERROR("unable to create", net::ERR_FILE_NOT_FOUND);
|
| + return LogInterruptReason("Unable to create", 0,
|
| + content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
|
| }
|
| full_path_ = temp_file;
|
| }
|
| @@ -268,7 +93,8 @@ net::Error BaseFile::Initialize(const FilePath& default_directory) {
|
| return Open();
|
| }
|
|
|
| -net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) {
|
| +content::DownloadInterruptReason BaseFile::AppendDataToFile(const char* data,
|
| + size_t data_len) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| DCHECK(!detached_);
|
|
|
| @@ -280,11 +106,12 @@ net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) {
|
| }
|
|
|
| if (!file_stream_.get())
|
| - return LOG_ERROR("get", net::ERR_INVALID_HANDLE);
|
| + return LogInterruptReason("No file stream on append", 0,
|
| + content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
|
|
|
| // TODO(phajdan.jr): get rid of this check.
|
| if (data_len == 0)
|
| - return net::OK;
|
| + return content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
|
|
| // The Write call below is not guaranteed to write all the data.
|
| size_t write_count = 0;
|
| @@ -303,7 +130,7 @@ net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) {
|
|
|
| // Report errors on file writes.
|
| if (write_result < 0)
|
| - return LOG_ERROR("Write", write_result);
|
| + return LogNetError("Write", static_cast<net::Error>(write_result));
|
| }
|
|
|
| // Update status.
|
| @@ -320,84 +147,43 @@ net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) {
|
| if (calculate_hash_)
|
| secure_hash_->Update(data, data_len);
|
|
|
| - return net::OK;
|
| + return content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
| }
|
|
|
| -net::Error BaseFile::Rename(const FilePath& new_path) {
|
| +content::DownloadInterruptReason BaseFile::Rename(const FilePath& new_path) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + content::DownloadInterruptReason rename_result =
|
| + content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
| +
|
| + // If the new path is same as the old one, there is no need to perform the
|
| + // following renaming logic.
|
| + if (new_path == full_path_)
|
| + return content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
|
|
| // Save the information whether the download is in progress because
|
| // it will be overwritten by closing the file.
|
| - bool saved_in_progress = in_progress();
|
| + bool was_in_progress = in_progress();
|
|
|
| - bound_net_log_.AddEvent(
|
| + bound_net_log_.BeginEvent(
|
| net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED,
|
| base::Bind(&download_net_logs::FileRenamedCallback,
|
| &full_path_, &new_path));
|
| -
|
| - // If the new path is same as the old one, there is no need to perform the
|
| - // following renaming logic.
|
| - if (new_path == full_path_) {
|
| - // Don't close the file if we're not done (finished or canceled).
|
| - if (!saved_in_progress)
|
| - Close();
|
| -
|
| - return net::OK;
|
| - }
|
| -
|
| Close();
|
| -
|
| file_util::CreateDirectory(new_path.DirName());
|
|
|
| -#if defined(OS_WIN)
|
| - // We cannot rename because rename will keep the same security descriptor
|
| - // on the destination file. We want to recreate the security descriptor
|
| - // with the security that makes sense in the new path.
|
| - // |RenameFileAndResetSecurityDescriptor| returns a windows-specific
|
| - // error, whch we must translate into a net::Error.
|
| - net::Error rename_err =
|
| - RenameFileAndResetSecurityDescriptor(full_path_, new_path);
|
| - if (rename_err != net::OK)
|
| - return LOG_ERROR("RenameFileAndResetSecurityDescriptor", rename_err);
|
| -#elif defined(OS_POSIX)
|
| - {
|
| - // Similarly, on Unix, we're moving a temp file created with permissions
|
| - // 600 to |new_path|. Here, we try to fix up the destination file with
|
| - // appropriate permissions.
|
| - struct stat st;
|
| - // First check the file existence and create an empty file if it doesn't
|
| - // exist.
|
| - if (!file_util::PathExists(new_path)) {
|
| - int write_error = file_util::WriteFile(new_path, "", 0);
|
| - if (write_error < 0)
|
| - return LOG_ERROR("WriteFile", net::MapSystemError(errno));
|
| - }
|
| - int stat_error = stat(new_path.value().c_str(), &st);
|
| - bool stat_succeeded = (stat_error == 0);
|
| - if (!stat_succeeded)
|
| - LOG_ERROR("stat", net::MapSystemError(errno));
|
| -
|
| - // TODO(estade): Move() falls back to copying and deleting when a simple
|
| - // rename fails. Copying sucks for large downloads. crbug.com/8737
|
| - if (!file_util::Move(full_path_, new_path))
|
| - return LOG_ERROR("Move", net::MapSystemError(errno));
|
| -
|
| - if (stat_succeeded) {
|
| - // On Windows file systems (FAT, NTFS), chmod fails. This is OK.
|
| - int chmod_error = chmod(new_path.value().c_str(), st.st_mode);
|
| - if (chmod_error < 0)
|
| - LOG_ERROR("chmod", net::MapSystemError(errno));
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - full_path_ = new_path;
|
| + // A simple rename wouldn't work here since we want the file to have
|
| + // permissions / security descriptors that makes sense in the new directory.
|
| + rename_result = MoveFileAndAdjustPermissions(new_path);
|
|
|
| - // We don't need to re-open the file if we're done (finished or canceled).
|
| - if (!saved_in_progress)
|
| - return net::OK;
|
| + if (rename_result == content::DOWNLOAD_INTERRUPT_REASON_NONE) {
|
| + full_path_ = new_path;
|
| + // Re-open the file if we were still using it.
|
| + if (was_in_progress)
|
| + rename_result = Open();
|
| + }
|
|
|
| - return Open();
|
| + bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED);
|
| + return rename_result;
|
| }
|
|
|
| void BaseFile::Detach() {
|
| @@ -429,6 +215,17 @@ void BaseFile::Finish() {
|
| Close();
|
| }
|
|
|
| +// OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations.
|
| +#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
|
| +void BaseFile::AnnotateWithSourceInformation() {
|
| +}
|
| +#endif
|
| +
|
| +int64 BaseFile::CurrentSpeed() const {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + return CurrentSpeedAtTime(base::TimeTicks::Now());
|
| +}
|
| +
|
| bool BaseFile::GetHash(std::string* hash) {
|
| DCHECK(!detached_);
|
| hash->assign(reinterpret_cast<const char*>(sha256_hash_),
|
| @@ -448,36 +245,21 @@ std::string BaseFile::GetHashState() {
|
| hash_state.size());
|
| }
|
|
|
| -bool BaseFile::SetHashState(const std::string& hash_state_bytes) {
|
| - if (!calculate_hash_)
|
| - return false;
|
| -
|
| - Pickle hash_state(hash_state_bytes.c_str(), hash_state_bytes.size());
|
| - PickleIterator data_iterator(hash_state);
|
| -
|
| - return secure_hash_->Deserialize(&data_iterator);
|
| -}
|
| -
|
| +// static
|
| bool BaseFile::IsEmptyHash(const std::string& hash) {
|
| return (hash.size() == kSha256HashLen &&
|
| 0 == memcmp(hash.data(), kEmptySha256Hash, sizeof(kSha256HashLen)));
|
| }
|
|
|
| -void BaseFile::AnnotateWithSourceInformation() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - DCHECK(!detached_);
|
| -
|
| -#if defined(OS_WIN)
|
| - // 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()));
|
| -#elif defined(OS_MACOSX)
|
| - content::AddQuarantineMetadataToFile(full_path_, source_url_, referrer_url_);
|
| - content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_);
|
| -#elif defined(OS_LINUX)
|
| - content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_);
|
| -#endif
|
| +std::string BaseFile::DebugString() const {
|
| + return base::StringPrintf("{ source_url_ = \"%s\""
|
| + " full_path_ = \"%" PRFilePath "\""
|
| + " bytes_so_far_ = %" PRId64
|
| + " detached_ = %c }",
|
| + source_url_.spec().c_str(),
|
| + full_path_.value().c_str(),
|
| + bytes_so_far_,
|
| + detached_ ? 'T' : 'F');
|
| }
|
|
|
| void BaseFile::CreateFileStream() {
|
| @@ -485,7 +267,7 @@ void BaseFile::CreateFileStream() {
|
| file_stream_->SetBoundNetLogSource(bound_net_log_);
|
| }
|
|
|
| -net::Error BaseFile::Open() {
|
| +content::DownloadInterruptReason BaseFile::Open() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| DCHECK(!detached_);
|
| DCHECK(!full_path_.empty());
|
| @@ -502,19 +284,23 @@ net::Error BaseFile::Open() {
|
| int open_result = file_stream_->OpenSync(
|
| full_path_,
|
| base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE);
|
| - if (open_result != net::OK)
|
| - return ClearStream(LOG_ERROR("Open", open_result));
|
| + if (open_result != net::OK) {
|
| + ClearStream();
|
| + return LogNetError("Open", static_cast<net::Error>(open_result));
|
| + }
|
|
|
| // We may be re-opening the file after rename. Always make sure we're
|
| // writing at the end of the file.
|
| int64 seek_result = file_stream_->SeekSync(net::FROM_END, 0);
|
| - if (seek_result < 0)
|
| - return ClearStream(LOG_ERROR("Seek", seek_result));
|
| + if (seek_result < 0) {
|
| + ClearStream();
|
| + return LogNetError("Seek", static_cast<net::Error>(seek_result));
|
| + }
|
| } else {
|
| file_stream_->SetBoundNetLogSource(bound_net_log_);
|
| }
|
|
|
| - return net::OK;
|
| + return content::DOWNLOAD_INTERRUPT_REASON_NONE;
|
| }
|
|
|
| void BaseFile::Close() {
|
| @@ -529,27 +315,15 @@ void BaseFile::Close() {
|
| file_stream_->FlushSync();
|
| #endif
|
| file_stream_->CloseSync();
|
| - ClearStream(net::OK);
|
| + ClearStream();
|
| }
|
| }
|
|
|
| -net::Error BaseFile::ClearStream(net::Error net_error) {
|
| +void BaseFile::ClearStream() {
|
| // This should only be called when we have a stream.
|
| DCHECK(file_stream_.get() != NULL);
|
| file_stream_.reset();
|
| bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_OPENED);
|
| - return net_error;
|
| -}
|
| -
|
| -std::string BaseFile::DebugString() const {
|
| - return base::StringPrintf("{ source_url_ = \"%s\""
|
| - " full_path_ = \"%" PRFilePath "\""
|
| - " bytes_so_far_ = %" PRId64
|
| - " detached_ = %c }",
|
| - source_url_.spec().c_str(),
|
| - full_path_.value().c_str(),
|
| - bytes_so_far_,
|
| - detached_ ? 'T' : 'F');
|
| }
|
|
|
| int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const {
|
| @@ -558,7 +332,34 @@ int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const {
|
| return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms;
|
| }
|
|
|
| -int64 BaseFile::CurrentSpeed() const {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - return CurrentSpeedAtTime(base::TimeTicks::Now());
|
| +content::DownloadInterruptReason BaseFile::LogNetError(
|
| + const char* operation,
|
| + net::Error error) {
|
| + bound_net_log_.AddEvent(
|
| + net::NetLog::TYPE_DOWNLOAD_FILE_ERROR,
|
| + base::Bind(&download_net_logs::FileErrorCallback, operation, error));
|
| + return content::ConvertNetErrorToInterruptReason(
|
| + error, content::DOWNLOAD_INTERRUPT_FROM_DISK);
|
| +}
|
| +
|
| +content::DownloadInterruptReason BaseFile::LogSystemError(
|
| + const char* operation,
|
| + int os_error) {
|
| + // There's no direct conversion from a system error to an interrupt reason.
|
| + net::Error net_error = net::MapSystemError(os_error);
|
| + return LogInterruptReason(
|
| + operation, os_error,
|
| + content::ConvertNetErrorToInterruptReason(
|
| + net_error, content::DOWNLOAD_INTERRUPT_FROM_DISK));
|
| +}
|
| +
|
| +content::DownloadInterruptReason BaseFile::LogInterruptReason(
|
| + const char* operation,
|
| + int os_error,
|
| + content::DownloadInterruptReason reason) {
|
| + bound_net_log_.AddEvent(
|
| + net::NetLog::TYPE_DOWNLOAD_FILE_ERROR,
|
| + base::Bind(&download_net_logs::FileInterruptedCallback, operation,
|
| + os_error, reason));
|
| + return reason;
|
| }
|
|
|