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 507dfe1692cbc5dd0da9e58ad25fe46649b23bfe..eead7f6142f1dd4aeac149901db3cd47a016e065 100644 |
--- a/content/browser/download/download_item_impl.cc |
+++ b/content/browser/download/download_item_impl.cc |
@@ -896,6 +896,50 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const { |
return mode; |
} |
+void DownloadItemImpl::MergeOriginInfoOnResume( |
+ const DownloadCreateInfo& new_create_info) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK_EQ(RESUMING_INTERNAL, state_); |
+ DCHECK(!new_create_info.url_chain.empty()); |
+ |
+ // We are going to tack on any new redirects to our list of redirects. |
+ // When a download is resumed, the URL used for the resumption request is the |
+ // one at the end of the previous redirect chain. Tacking additional redirects |
+ // to the end of this chain ensures that: |
+ // - If the download needs to be resumed again, the ETag/Last-Modified headers |
+ // will be used with the last server that sent them to us. |
+ // - The redirect chain contains all the servers that were involved in this |
+ // download since the initial request, in order. |
+ std::vector<GURL>::const_iterator chain_iter = |
+ new_create_info.url_chain.begin(); |
+ if (*chain_iter == url_chain_.back()) |
+ ++chain_iter; |
+ |
+ // Record some stats. If the precondition failed (the server returned |
+ // HTTP_PRECONDITION_FAILED), then the download will automatically retried as |
+ // a full request rather than a partial. Full restarts clobber validators. |
+ int origin_state = 0; |
+ if (chain_iter != new_create_info.url_chain.end()) |
+ origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS; |
+ if (etag_ != new_create_info.etag || |
+ last_modified_time_ != new_create_info.last_modified) |
+ 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); |
+ |
+ url_chain_.insert( |
+ url_chain_.end(), chain_iter, new_create_info.url_chain.end()); |
+ etag_ = new_create_info.etag; |
+ last_modified_time_ = new_create_info.last_modified; |
+ content_disposition_ = new_create_info.content_disposition; |
+ |
+ // Don't update observers. This method is expected to be called just before a |
+ // DownloadFile is created and Start() is called. The observers will be |
+ // notified when the download transitions to the IN_PROGRESS state. |
+} |
+ |
void DownloadItemImpl::NotifyRemoved() { |
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); |
} |