| 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);
|
| }
|
|
|