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 e2e86a34eb6a3f602ef7b2566eefd0982ff4fdb7..a4630a391fea2f550c2ef07f90ad6cd49f8d187f 100644 |
--- a/content/browser/download/download_item_impl.cc |
+++ b/content/browser/download/download_item_impl.cc |
@@ -151,23 +151,23 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); |
} |
-// Constructing for a regular download: |
-DownloadItemImpl::DownloadItemImpl( |
- DownloadItemImplDelegate* delegate, |
- uint32 download_id, |
- const DownloadCreateInfo& info, |
- const net::BoundNetLog& bound_net_log) |
- : is_save_package_download_(false), |
+// Constructing for a regular download (also includes SavePackage downloads): |
+DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
+ uint32 download_id, |
+ const DownloadCreateInfo& info, |
+ const net::BoundNetLog& bound_net_log) |
+ : is_save_package_download_(info.is_save_package_download), |
download_id_(download_id), |
- target_disposition_( |
- (info.save_info->prompt_for_save_location) ? |
- TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), |
+ target_disposition_((info.save_info->prompt_for_save_location) |
+ ? TARGET_DISPOSITION_PROMPT |
+ : TARGET_DISPOSITION_OVERWRITE), |
url_chain_(info.url_chain), |
referrer_url_(info.referrer_url), |
suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)), |
forced_file_path_(info.save_info->file_path), |
transition_type_(info.transition_type), |
has_user_gesture_(info.has_user_gesture), |
+ route_id_(info.route_id), |
content_disposition_(info.content_disposition), |
mime_type_(info.mime_type), |
original_mime_type_(info.original_mime_type), |
@@ -196,62 +196,22 @@ DownloadItemImpl::DownloadItemImpl( |
bound_net_log_(bound_net_log), |
weak_ptr_factory_(this) { |
delegate_->Attach(); |
- Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); |
+ Init(true /* actively downloading */, |
+ is_save_package_download_ ? SRC_SAVE_PAGE_AS : SRC_ACTIVE_DOWNLOAD); |
- // Link the event sources. |
- bound_net_log_.AddEvent( |
- net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, |
- info.request_bound_net_log.source().ToEventParametersCallback()); |
+ if (is_save_package_download_) { |
+ current_path_ = info.save_info->file_path; |
+ target_path_ = current_path_; |
+ } else { |
+ // Link the event sources. |
+ bound_net_log_.AddEvent( |
+ net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, |
+ info.request_bound_net_log.source().ToEventParametersCallback()); |
info.request_bound_net_log.AddEvent( |
net::NetLog::TYPE_DOWNLOAD_STARTED, |
bound_net_log_.source().ToEventParametersCallback()); |
-} |
- |
-// Constructing for the "Save Page As..." feature: |
-DownloadItemImpl::DownloadItemImpl( |
- DownloadItemImplDelegate* delegate, |
- uint32 download_id, |
- const base::FilePath& path, |
- const GURL& url, |
- const std::string& mime_type, |
- scoped_ptr<DownloadRequestHandleInterface> request_handle, |
- const net::BoundNetLog& bound_net_log) |
- : is_save_package_download_(true), |
- request_handle_(request_handle.Pass()), |
- download_id_(download_id), |
- current_path_(path), |
- target_path_(path), |
- target_disposition_(TARGET_DISPOSITION_OVERWRITE), |
- url_chain_(1, url), |
- referrer_url_(GURL()), |
- transition_type_(PAGE_TRANSITION_LINK), |
- has_user_gesture_(false), |
- mime_type_(mime_type), |
- original_mime_type_(mime_type), |
- total_bytes_(0), |
- received_bytes_(0), |
- bytes_per_sec_(0), |
- last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), |
- start_tick_(base::TimeTicks::Now()), |
- state_(IN_PROGRESS_INTERNAL), |
- danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
- start_time_(base::Time::Now()), |
- delegate_(delegate), |
- is_paused_(false), |
- auto_resume_count_(0), |
- open_when_complete_(false), |
- file_externally_removed_(false), |
- auto_opened_(false), |
- is_temporary_(false), |
- all_data_saved_(false), |
- destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE), |
- opened_(false), |
- delegate_delayed_complete_(false), |
- bound_net_log_(bound_net_log), |
- weak_ptr_factory_(this) { |
- delegate_->Attach(); |
- Init(true /* actively downloading */, SRC_SAVE_PAGE_AS); |
+ } |
} |
DownloadItemImpl::~DownloadItemImpl() { |
@@ -330,7 +290,7 @@ void DownloadItemImpl::Pause() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Ignore irrelevant states. |
- if (state_ != IN_PROGRESS_INTERNAL || is_paused_) |
+ if (state_ != IN_PROGRESS_INTERNAL || is_paused_ || !request_handle_) |
return; |
request_handle_->PauseRequest(); |
@@ -340,6 +300,8 @@ void DownloadItemImpl::Pause() { |
void DownloadItemImpl::Resume() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!request_handle_) |
+ return; |
switch (state_) { |
case IN_PROGRESS_INTERNAL: |
if (!is_paused_) |
@@ -395,7 +357,7 @@ void DownloadItemImpl::Cancel(bool user_cancel) { |
if (!is_save_package_download_ && download_file_) |
ReleaseDownloadFile(true); |
- if (state_ == IN_PROGRESS_INTERNAL) { |
+ if (state_ == IN_PROGRESS_INTERNAL && request_handle_) { |
// Cancel the originating URL request unless it's already been cancelled |
// by interrupt. |
request_handle_->CancelRequest(); |
@@ -484,11 +446,6 @@ bool DownloadItemImpl::CanResume() const { |
if (state_ != INTERRUPTED_INTERNAL) |
return false; |
- // Downloads that don't have a WebContents should still be resumable, but this |
- // isn't currently the case. See ResumeInterruptedDownload(). |
- if (!GetWebContents()) |
- return false; |
- |
ResumeMode resume_mode = GetResumeMode(); |
return IsDownloadResumptionEnabled() && |
(resume_mode == RESUME_MODE_USER_RESTART || |
@@ -730,13 +687,15 @@ BrowserContext* DownloadItemImpl::GetBrowserContext() const { |
} |
WebContents* DownloadItemImpl::GetWebContents() const { |
- // TODO(rdsmith): Remove null check after removing GetWebContents() from |
- // paths that might be used by DownloadItems created from history import. |
- // Currently such items have null request_handle_s, where other items |
- // (regular and SavePackage downloads) have actual objects off the pointer. |
- if (request_handle_) |
- return request_handle_->GetWebContents(); |
- return NULL; |
+ if (route_id_ == GlobalRoutingID()) |
+ return NULL; |
+ |
+ RenderViewHostImpl* render_view_host = |
+ RenderViewHostImpl::FromID(route_id_.child_id, route_id_.route_id); |
+ if (!render_view_host) |
+ return NULL; |
+ |
+ return render_view_host->GetDelegate()->GetAsWebContents(); |
} |
void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type) { |
@@ -803,7 +762,7 @@ std::string DownloadItemImpl::DebugString(bool verbose) const { |
" target_path = \"%" PRFilePath "\"", |
GetTotalBytes(), |
GetReceivedBytes(), |
- InterruptReasonDebugString(last_reason_).c_str(), |
+ DownloadInterruptReasonToString(last_reason_).c_str(), |
IsPaused() ? 'T' : 'F', |
DebugResumeModeString(GetResumeMode()), |
auto_resume_count_, |
@@ -864,6 +823,7 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const { |
case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED: |
case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED: |
case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN: |
+ case DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST: |
case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED: |
case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN: |
case DOWNLOAD_INTERRUPT_REASON_CRASH: |
@@ -894,6 +854,37 @@ 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. |
+ std::vector<GURL>::const_iterator chain_iter = |
+ new_create_info.url_chain.begin(); |
+ if (*chain_iter == url_chain_.back()) |
+ ++chain_iter; |
+ url_chain_.insert( |
+ url_chain_.end(), chain_iter, new_create_info.url_chain.end()); |
+ // TODO(asanka): Measure how URL chains change with resumption. Resumption |
+ // requests are issued against the actual download URL and we don't expect any |
+ // redirects. |
+ |
+ // If the server precondition failed, then the download will be resumed |
+ // automatically without validators. |
+ etag_ = new_create_info.etag; |
+ last_modified_time_ = new_create_info.last_modified; |
+ content_disposition_ = new_create_info.content_disposition; |
+ // TODO(asanka): Measure how validators change with resumption. I.e. An ETag |
+ // should only change if we used it and the server responded with |
+ // HTTP_PRECONDITION_FAILED. |
+ |
+ // 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)); |
} |
@@ -1033,9 +1024,8 @@ void DownloadItemImpl::Init(bool active, |
} |
// We're starting the download. |
-void DownloadItemImpl::Start( |
- scoped_ptr<DownloadFile> file, |
- scoped_ptr<DownloadRequestHandleInterface> req_handle) { |
+void DownloadItemImpl::Start(scoped_ptr<DownloadFile> file, |
+ scoped_ptr<DownloadRequestHandle> req_handle) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DCHECK(!download_file_.get()); |
DCHECK(file.get()); |
@@ -1332,23 +1322,20 @@ void DownloadItemImpl::Completed() { |
} |
} |
-void DownloadItemImpl::OnResumeRequestStarted(DownloadItem* item, |
- net::Error error) { |
+void DownloadItemImpl::OnResumeRequestStarted( |
+ DownloadItem* item, |
+ DownloadInterruptReason interrupt_reason) { |
// If |item| is not NULL, then Start() has been called already, and nothing |
// more needs to be done here. |
if (item) { |
- DCHECK_EQ(net::OK, error); |
+ DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); |
DCHECK_EQ(static_cast<DownloadItem*>(this), item); |
return; |
} |
// Otherwise, the request failed without passing through |
// DownloadResourceHandler::OnResponseStarted. |
- if (error == net::OK) |
- error = net::ERR_FAILED; |
- DownloadInterruptReason reason = |
- ConvertNetErrorToInterruptReason(error, DOWNLOAD_INTERRUPT_FROM_NETWORK); |
- DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); |
- Interrupt(reason); |
+ DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); |
+ Interrupt(interrupt_reason); |
} |
// **** End of Download progression cascade |
@@ -1383,7 +1370,8 @@ void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
!IsDownloadResumptionEnabled()); |
// Cancel the originating URL request. |
- request_handle_->CancelRequest(); |
+ if (request_handle_) |
+ request_handle_->CancelRequest(); |
} else { |
DCHECK(!download_file_.get()); |
} |
@@ -1590,13 +1578,6 @@ void DownloadItemImpl::ResumeInterruptedDownload() { |
if (state_ != INTERRUPTED_INTERNAL) |
return; |
- // If we can't get a web contents, we can't resume the download. |
- // TODO(rdsmith): Find some alternative web contents to use--this |
- // means we can't restart a download if it's a download imported |
- // from the history. |
- if (!GetWebContents()) |
- return; |
- |
// Reset the appropriate state if restarting. |
ResumeMode mode = GetResumeMode(); |
if (mode == RESUME_MODE_IMMEDIATE_RESTART || |
@@ -1607,9 +1588,16 @@ void DownloadItemImpl::ResumeInterruptedDownload() { |
etag_ = ""; |
} |
+ // Just in case we were interrupted while paused. |
+ is_paused_ = false; |
+ |
+ // TODO(asanka): The resource context may not be correct if the original |
+ // request was associated with a different storage partition. |
scoped_ptr<DownloadUrlParameters> download_params( |
- DownloadUrlParameters::FromWebContents(GetWebContents(), |
- GetOriginalUrl())); |
+ new DownloadUrlParameters(GetOriginalUrl(), |
+ route_id_.child_id, |
+ route_id_.route_id, |
+ GetBrowserContext()->GetResourceContext())); |
download_params->set_file_path(GetFullPath()); |
download_params->set_offset(GetReceivedBytes()); |
@@ -1621,8 +1609,6 @@ void DownloadItemImpl::ResumeInterruptedDownload() { |
weak_ptr_factory_.GetWeakPtr())); |
delegate_->ResumeInterruptedDownload(download_params.Pass(), GetId()); |
- // Just in case we were interrupted while paused. |
- is_paused_ = false; |
TransitionTo(RESUMING_INTERNAL, DONT_UPDATE_OBSERVERS); |
} |