Index: content/browser/download/download_item_impl.cc |
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc |
index 19e4675a60b915a34a8f46827aadea2c3d3fa1f8..08d90390a6098da9548ac813e5004c3ea8f19491 100644 |
--- a/content/browser/download/download_item_impl.cc |
+++ b/content/browser/download/download_item_impl.cc |
@@ -40,6 +40,7 @@ |
#include "content/browser/download/download_file.h" |
#include "content/browser/download/download_interrupt_reasons_impl.h" |
#include "content/browser/download/download_item_impl_delegate.h" |
+#include "content/browser/download/download_net_log_parameters.h" |
#include "content/browser/download/download_request_handle.h" |
#include "content/browser/download/download_stats.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
@@ -100,8 +101,6 @@ bool IsDownloadResumptionEnabled() { |
const uint32_t DownloadItem::kInvalidId = 0; |
-const char DownloadItem::kEmptyFileHash[] = ""; |
- |
// The maximum number of attempts we will make to resume automatically. |
const int DownloadItemImpl::kMaxAutoResumeAttempts = 5; |
@@ -121,6 +120,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
const std::string& last_modified, |
int64_t received_bytes, |
int64_t total_bytes, |
+ const std::string& hash, |
DownloadItem::DownloadState state, |
DownloadDangerType danger_type, |
DownloadInterruptReason interrupt_reason, |
@@ -128,16 +128,12 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
const net::BoundNetLog& bound_net_log) |
: guid_(base::ToUpperASCII(guid)), |
download_id_(download_id), |
- current_path_(current_path), |
target_path_(target_path), |
url_chain_(url_chain), |
referrer_url_(referrer_url), |
mime_type_(mime_type), |
original_mime_type_(original_mime_type), |
total_bytes_(total_bytes), |
- received_bytes_(received_bytes), |
- last_modified_time_(last_modified), |
- etag_(etag), |
last_reason_(interrupt_reason), |
start_tick_(base::TimeTicks()), |
state_(ExternalToInternalState(state)), |
@@ -145,8 +141,13 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
start_time_(start_time), |
end_time_(end_time), |
delegate_(delegate), |
- all_data_saved_(state == COMPLETE), |
opened_(opened), |
+ current_path_(current_path), |
+ received_bytes_(received_bytes), |
+ all_data_saved_(state == COMPLETE), |
+ hash_(hash), |
+ last_modified_time_(last_modified), |
+ etag_(etag), |
bound_net_log_(bound_net_log), |
weak_ptr_factory_(this) { |
delegate_->Attach(); |
@@ -179,14 +180,14 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
original_mime_type_(info.original_mime_type), |
remote_address_(info.remote_address), |
total_bytes_(info.total_bytes), |
- last_modified_time_(info.last_modified), |
- etag_(info.etag), |
last_reason_(info.result), |
start_tick_(base::TimeTicks::Now()), |
state_(INITIAL_INTERNAL), |
start_time_(info.start_time), |
delegate_(delegate), |
is_temporary_(!info.save_info->file_path.empty()), |
+ last_modified_time_(info.last_modified), |
+ etag_(info.etag), |
bound_net_log_(bound_net_log), |
weak_ptr_factory_(this) { |
delegate_->Attach(); |
@@ -215,7 +216,6 @@ DownloadItemImpl::DownloadItemImpl( |
request_handle_(std::move(request_handle)), |
guid_(base::ToUpperASCII(base::GenerateGUID())), |
download_id_(download_id), |
- current_path_(path), |
target_path_(path), |
url_chain_(1, url), |
mime_type_(mime_type), |
@@ -224,6 +224,7 @@ DownloadItemImpl::DownloadItemImpl( |
state_(IN_PROGRESS_INTERNAL), |
start_time_(base::Time::Now()), |
delegate_(delegate), |
+ current_path_(path), |
bound_net_log_(bound_net_log), |
weak_ptr_factory_(this) { |
delegate_->Attach(); |
@@ -378,8 +379,9 @@ void DownloadItemImpl::Resume() { |
void DownloadItemImpl::Cancel(bool user_cancel) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); |
- Interrupt(user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED |
- : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); |
+ InterruptAndDiscardPartialState( |
+ user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED |
+ : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); |
UpdateObservers(); |
} |
@@ -388,7 +390,7 @@ void DownloadItemImpl::Remove() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
delegate_->AssertStateConsistent(this); |
- Interrupt(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); |
+ InterruptAndDiscardPartialState(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); |
UpdateObservers(); |
delegate_->AssertStateConsistent(this); |
@@ -601,10 +603,6 @@ const std::string& DownloadItemImpl::GetHash() const { |
return hash_; |
} |
-const std::string& DownloadItemImpl::GetHashState() const { |
- return hash_state_; |
-} |
- |
bool DownloadItemImpl::GetFileExternallyRemoved() const { |
return file_externally_removed_; |
} |
@@ -796,8 +794,7 @@ std::string DownloadItemImpl::DebugString(bool verbose) const { |
if (verbose) { |
description += base::StringPrintf( |
- " total = %" PRId64 |
- " received = %" PRId64 |
+ " total = %" PRId64 " received = %" PRId64 |
" reason = %s" |
" paused = %c" |
" resume_mode = %s" |
@@ -808,7 +805,8 @@ std::string DownloadItemImpl::DebugString(bool verbose) const { |
" etag = '%s'" |
" has_download_file = %s" |
" url_chain = \n\t\"%s\"\n\t" |
- " full_path = \"%" PRFilePath "\"\n\t" |
+ " current_path = \"%" PRFilePath |
+ "\"\n\t" |
" target_path = \"%" PRFilePath "\"", |
GetTotalBytes(), |
GetReceivedBytes(), |
@@ -862,10 +860,14 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const { |
case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE: |
// The server disagreed with the file offset that we sent. |
+ case DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH: |
+ // The file on disk was found to not match the expected hash. Discard and |
+ // start from beginning. |
+ |
case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT: |
// The [possibly persisted] file offset disagreed with the file on disk. |
- // The intermediate stub is not usable and the server is resonding. Hence |
+ // The intermediate stub is not usable and the server is responding. Hence |
// retrying the request from the beginning is likely to work. |
restart_required = true; |
break; |
@@ -957,8 +959,7 @@ void DownloadItemImpl::UpdateValidatorsOnResumption( |
origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED; |
if (content_disposition_ != new_create_info.content_disposition) |
origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED; |
- RecordOriginStateOnResumption(new_create_info.save_info->offset != 0, |
- origin_state); |
+ RecordOriginStateOnResumption(received_bytes_ != 0, origin_state); |
url_chain_.insert( |
url_chain_.end(), chain_iter, new_create_info.url_chain.end()); |
@@ -994,16 +995,20 @@ void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) { |
total_bytes_ = total_bytes; |
} |
-void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) { |
+void DownloadItemImpl::OnAllDataSaved( |
+ int64_t total_bytes, |
+ scoped_ptr<crypto::SecureHash> hash_state) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
DCHECK(!all_data_saved_); |
all_data_saved_ = true; |
- DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
- |
- // Store final hash and null out intermediate serialized hash state. |
- hash_ = final_hash; |
- hash_state_ = ""; |
+ SetTotalBytes(total_bytes); |
+ UpdateProgress(total_bytes, 0); |
+ SetHashState(std::move(hash_state)); |
+ hash_state_.reset(); // No need to retain hash_state_ since we are done with |
+ // the download and don't expect to receive any more |
+ // data. |
+ DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
UpdateObservers(); |
} |
@@ -1017,8 +1022,7 @@ void DownloadItemImpl::MarkAsComplete() { |
} |
void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, |
- int64_t bytes_per_sec, |
- const std::string& hash_state) { |
+ int64_t bytes_per_sec) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
// If the download is in any other state we don't expect any |
// DownloadDestinationObserver callbacks. An interruption or a cancellation |
@@ -1026,19 +1030,15 @@ void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, |
// reference held by the DownloadFile and hence cuts off any pending |
// callbacks. |
DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); |
+ |
+ // There must be no pending destination_error_. |
+ DCHECK_EQ(destination_error_, DOWNLOAD_INTERRUPT_REASON_NONE); |
+ |
DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far |
<< " per_sec=" << bytes_per_sec |
<< " download=" << DebugString(true); |
- bytes_per_sec_ = bytes_per_sec; |
- hash_state_ = hash_state; |
- received_bytes_ = bytes_so_far; |
- |
- // If we've received more data than we were expecting (bad server info?), |
- // revert to 'unknown size mode'. |
- if (received_bytes_ > total_bytes_) |
- total_bytes_ = 0; |
- |
+ UpdateProgress(bytes_so_far, bytes_per_sec); |
if (bound_net_log_.IsCapturing()) { |
bound_net_log_.AddEvent( |
net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, |
@@ -1048,7 +1048,10 @@ void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, |
UpdateObservers(); |
} |
-void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { |
+void DownloadItemImpl::DestinationError( |
+ DownloadInterruptReason reason, |
+ int64_t bytes_so_far, |
+ scoped_ptr<crypto::SecureHash> secure_hash) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
// If the download is in any other state we don't expect any |
// DownloadDestinationObserver callbacks. An interruption or a cancellation |
@@ -1063,14 +1066,19 @@ void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { |
// has completed and the intermediate file has been renamed to simplify |
// resumption conditions. |
if (state_ == TARGET_PENDING_INTERNAL) { |
+ received_bytes_ = bytes_so_far; |
+ hash_state_ = std::move(secure_hash); |
+ hash_.clear(); |
destination_error_ = reason; |
return; |
} |
- Interrupt(reason); |
+ InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason); |
UpdateObservers(); |
} |
-void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { |
+void DownloadItemImpl::DestinationCompleted( |
+ int64_t total_bytes, |
+ scoped_ptr<crypto::SecureHash> secure_hash) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
// If the download is in any other state we don't expect any |
// DownloadDestinationObserver callbacks. An interruption or a cancellation |
@@ -1080,7 +1088,7 @@ void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { |
DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); |
DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
- OnAllDataSaved(final_hash); |
+ OnAllDataSaved(total_bytes, std::move(secure_hash)); |
MaybeCompleteDownload(); |
} |
@@ -1159,10 +1167,23 @@ void DownloadItemImpl::Start( |
if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
DCHECK(!download_file_.get()); |
+ // Download requests that are interrupted by Start() should result in a |
+ // DownloadCreateInfo with an intact DownloadSaveInfo. |
+ DCHECK(new_create_info.save_info); |
+ |
+ int64_t offset = new_create_info.save_info->offset; |
+ scoped_ptr<crypto::SecureHash> hash_state = |
+ make_scoped_ptr(new_create_info.save_info->hash_state |
+ ? new_create_info.save_info->hash_state->Clone() |
+ : nullptr); |
+ |
// Interrupted downloads also need a target path. |
if (target_path_.empty()) { |
- TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); |
+ received_bytes_ = offset; |
+ hash_state_ = std::move(hash_state); |
+ hash_.clear(); |
destination_error_ = new_create_info.result; |
+ TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); |
DetermineDownloadTarget(); |
return; |
} |
@@ -1170,7 +1191,8 @@ void DownloadItemImpl::Start( |
// Otherwise, this was a resumption attempt which ended with an |
// interruption. Continue with current target path. |
TransitionTo(TARGET_RESOLVED_INTERNAL); |
- Interrupt(new_create_info.result); |
+ InterruptWithPartialState( |
+ offset, std::move(hash_state), new_create_info.result); |
UpdateObservers(); |
return; |
} |
@@ -1200,7 +1222,12 @@ void DownloadItemImpl::OnDownloadFileInitialized( |
DVLOG(20) << __FUNCTION__ |
<< "() result:" << DownloadInterruptReasonToString(result); |
if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
- // Whoops. That didn't work. Proceed as an interrupted download. |
+ // Whoops. That didn't work. Proceed as an interrupted download, but reset |
+ // the partial state. Currently, the partial stub cannot be recovered if the |
+ // download file initialization fails. |
+ received_bytes_ = 0; |
+ hash_state_.reset(); |
+ hash_.clear(); |
destination_error_ = result; |
TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); |
} |
@@ -1245,7 +1272,8 @@ void DownloadItemImpl::OnDownloadTargetDetermined( |
// This was an interrupted download that was looking for a filename. Now that |
// it has one, transition to interrupted. |
if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) { |
- Interrupt(destination_error_); |
+ InterruptWithPartialState( |
+ received_bytes_, std::move(hash_state_), destination_error_); |
destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; |
UpdateObservers(); |
return; |
@@ -1293,33 +1321,36 @@ void DownloadItemImpl::OnDownloadRenamedToIntermediateName( |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); |
DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); |
+ |
TransitionTo(TARGET_RESOLVED_INTERNAL); |
- if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { |
- // Process destination error. If both |reason| and |destination_error_| |
- // refer to actual errors, we want to use the |destination_error_| as the |
- // argument to the Interrupt() routine, as it happened first. |
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) |
- SetFullPath(full_path); |
- Interrupt(destination_error_); |
- destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; |
- UpdateObservers(); |
- } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
- Interrupt(reason); |
- // All file errors result in file deletion above; no need to cleanup. The |
- // current_path_ should be empty. Resuming this download will force a |
- // restart and a re-doing of filename determination. |
- DCHECK(current_path_.empty()); |
+ // If the intermediate rename fails while there's also a destination_error_, |
+ // then the former is considered the critical error since it requires |
+ // discarding the partial state. |
+ if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
+ // TODO(asanka): Even though the rename failed, it may still be possible to |
+ // recover the partial state from the 'before' name. |
+ InterruptAndDiscardPartialState(reason); |
UpdateObservers(); |
- } else { |
+ return; |
+ } |
+ |
+ if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { |
SetFullPath(full_path); |
- TransitionTo(IN_PROGRESS_INTERNAL); |
- // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() |
- // is not safe. The download could be in an underminate state after invoking |
- // observers. http://crbug.com/586610 |
+ InterruptWithPartialState( |
+ received_bytes_, std::move(hash_state_), destination_error_); |
+ destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; |
UpdateObservers(); |
- MaybeCompleteDownload(); |
+ return; |
} |
+ |
+ SetFullPath(full_path); |
+ TransitionTo(IN_PROGRESS_INTERNAL); |
+ // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is |
+ // not safe. The download could be in an underminate state after invoking |
+ // observers. http://crbug.com/586610 |
+ UpdateObservers(); |
+ MaybeCompleteDownload(); |
} |
// When SavePackage downloads MHTML to GData (see |
@@ -1379,10 +1410,15 @@ void DownloadItemImpl::OnDownloadCompleting() { |
base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, |
weak_ptr_factory_.GetWeakPtr()); |
BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
+ BrowserThread::FILE, |
+ FROM_HERE, |
base::Bind(&DownloadFile::RenameAndAnnotate, |
base::Unretained(download_file_.get()), |
- GetTargetFilePath(), callback)); |
+ GetTargetFilePath(), |
+ delegate_->GetApplicationClientIdForFileScanning(), |
+ GetURL(), |
+ GetReferrerUrl(), |
+ callback)); |
} |
void DownloadItemImpl::OnDownloadRenamedToFinalName( |
@@ -1402,11 +1438,10 @@ void DownloadItemImpl::OnDownloadRenamedToFinalName( |
<< " " << DebugString(false); |
if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
- Interrupt(reason); |
- |
- // All file errors should have resulted in in file deletion above. On |
- // resumption we will need to re-do filename determination. |
- DCHECK(current_path_.empty()); |
+ // Failure to perform the final rename is considered fatal. TODO(asanka): It |
+ // may not be, in which case we should figure out whether we can recover the |
+ // state. |
+ InterruptAndDiscardPartialState(reason); |
UpdateObservers(); |
return; |
} |
@@ -1474,12 +1509,21 @@ void DownloadItemImpl::Completed() { |
// **** End of Download progression cascade |
-// An error occurred somewhere. |
-void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
+void DownloadItemImpl::InterruptAndDiscardPartialState( |
+ DownloadInterruptReason reason) { |
+ InterruptWithPartialState(0, scoped_ptr<crypto::SecureHash>(), reason); |
+} |
+ |
+void DownloadItemImpl::InterruptWithPartialState( |
+ int64_t bytes_so_far, |
+ scoped_ptr<crypto::SecureHash> hash_state, |
+ DownloadInterruptReason reason) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); |
DVLOG(20) << __FUNCTION__ |
<< "() reason:" << DownloadInterruptReasonToString(reason) |
+ << " bytes_so_far:" << bytes_so_far |
+ << " hash_state:" << (hash_state ? "Valid" : "Invalid") |
<< " this=" << DebugString(true); |
// Somewhat counter-intuitively, it is possible for us to receive an |
@@ -1520,6 +1564,7 @@ void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
case RESUMING_INTERNAL: |
case INTERRUPTED_INTERNAL: |
+ DCHECK(!download_file_); |
// The first non-cancel interrupt reason wins in cases where multiple |
// things go wrong. |
if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && |
@@ -1551,6 +1596,15 @@ void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
// behave properly with setting all_data_saved_ to false here. |
all_data_saved_ = false; |
+ if (current_path_.empty()) { |
+ hash_state_.reset(); |
+ hash_.clear(); |
+ received_bytes_ = 0; |
+ } else { |
+ UpdateProgress(bytes_so_far, 0); |
+ SetHashState(std::move(hash_state)); |
+ } |
+ |
if (request_handle_) |
request_handle_->CancelRequest(); |
@@ -1577,6 +1631,30 @@ void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
AutoResumeIfValid(); |
} |
+void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far, |
+ int64_t bytes_per_sec) { |
+ received_bytes_ = bytes_so_far; |
+ bytes_per_sec_ = bytes_per_sec; |
+ |
+ // If we've received more data than we were expecting (bad server info?), |
+ // revert to 'unknown size mode'. |
+ if (received_bytes_ > total_bytes_) |
+ total_bytes_ = 0; |
+} |
+ |
+void DownloadItemImpl::SetHashState(scoped_ptr<crypto::SecureHash> hash_state) { |
+ hash_state_ = std::move(hash_state); |
+ if (!hash_state_) { |
+ hash_.clear(); |
+ return; |
+ } |
+ |
+ scoped_ptr<crypto::SecureHash> clone_of_hash_state(hash_state_->Clone()); |
+ std::vector<char> hash_value(clone_of_hash_state->GetHashLength()); |
+ clone_of_hash_state->Finish(&hash_value.front(), hash_value.size()); |
+ hash_.assign(hash_value.begin(), hash_value.end()); |
+} |
+ |
void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file; |
@@ -1694,22 +1772,22 @@ void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { |
case INTERRUPTED_INTERNAL: |
bound_net_log_.AddEvent( |
net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, |
- base::Bind(&ItemInterruptedNetLogCallback, last_reason_, |
- received_bytes_, &hash_state_)); |
+ base::Bind( |
+ &ItemInterruptedNetLogCallback, last_reason_, received_bytes_)); |
break; |
case RESUMING_INTERNAL: |
- bound_net_log_.AddEvent( |
- net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, |
- base::Bind(&ItemResumingNetLogCallback, false, last_reason_, |
- received_bytes_, &hash_state_)); |
+ bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, |
+ base::Bind(&ItemResumingNetLogCallback, |
+ false, |
+ last_reason_, |
+ received_bytes_)); |
break; |
case CANCELLED_INTERNAL: |
bound_net_log_.AddEvent( |
net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, |
- base::Bind(&ItemCanceledNetLogCallback, received_bytes_, |
- &hash_state_)); |
+ base::Bind(&ItemCanceledNetLogCallback, received_bytes_)); |
break; |
case MAX_DOWNLOAD_INTERNAL_STATE: |
@@ -1810,9 +1888,10 @@ void DownloadItemImpl::ResumeInterruptedDownload() { |
if (mode == RESUME_MODE_IMMEDIATE_RESTART || |
mode == RESUME_MODE_USER_RESTART) { |
received_bytes_ = 0; |
- hash_state_ = ""; |
- last_modified_time_ = ""; |
- etag_ = ""; |
+ last_modified_time_.clear(); |
+ etag_.clear(); |
+ hash_.clear(); |
+ hash_state_.reset(); |
} |
// Avoid using the WebContents even if it's still around. Resumption requests |
@@ -1823,9 +1902,10 @@ void DownloadItemImpl::ResumeInterruptedDownload() { |
GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext())); |
download_params->set_file_path(GetFullPath()); |
download_params->set_offset(GetReceivedBytes()); |
- download_params->set_hash_state(GetHashState()); |
download_params->set_last_modified(GetLastModifiedTime()); |
download_params->set_etag(GetETag()); |
+ download_params->set_hash_of_partial_file(hash_); |
+ download_params->set_hash_state(std::move(hash_state_)); |
TransitionTo(RESUMING_INTERNAL); |
delegate_->ResumeInterruptedDownload(std::move(download_params), GetId()); |