Index: content/browser/download/download_manager_impl.cc |
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc |
index ccfb4cc0a5111a7eb5fcfd0ba87060ded15cf770..4ccab3a3e1c9fcd4d605664a248e4e29ae339aa7 100644 |
--- a/content/browser/download/download_manager_impl.cc |
+++ b/content/browser/download/download_manager_impl.cc |
@@ -24,6 +24,7 @@ |
#include "content/browser/download/download_item_factory.h" |
#include "content/browser/download/download_item_impl.h" |
#include "content/browser/download/download_stats.h" |
+#include "content/browser/download/url_downloader.h" |
#include "content/browser/loader/resource_dispatcher_host_impl.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
#include "content/browser/web_contents/web_contents_impl.h" |
@@ -47,91 +48,6 @@ |
namespace content { |
namespace { |
-void BeginDownload(scoped_ptr<DownloadUrlParameters> params, |
- uint32 download_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
- // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
- // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
- scoped_ptr<net::URLRequest> request( |
- params->resource_context()->GetRequestContext()->CreateRequest( |
- params->url(), NULL)); |
- request->set_load_flags(request->load_flags() | params->load_flags()); |
- request->set_method(params->method()); |
- if (!params->post_body().empty()) { |
- const std::string& body = params->post_body(); |
- scoped_ptr<net::UploadElementReader> reader( |
- net::UploadOwnedBytesElementReader::CreateWithString(body)); |
- request->set_upload(make_scoped_ptr( |
- net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); |
- } |
- if (params->post_id() >= 0) { |
- // The POST in this case does not have an actual body, and only works |
- // when retrieving data from cache. This is done because we don't want |
- // to do a re-POST without user consent, and currently don't have a good |
- // plan on how to display the UI for that. |
- DCHECK(params->prefer_cache()); |
- DCHECK(params->method() == "POST"); |
- ScopedVector<net::UploadElementReader> element_readers; |
- request->set_upload(make_scoped_ptr( |
- new net::UploadDataStream(&element_readers, params->post_id()))); |
- } |
- |
- // If we're not at the beginning of the file, retrieve only the remaining |
- // portion. |
- bool has_last_modified = !params->last_modified().empty(); |
- bool has_etag = !params->etag().empty(); |
- |
- // If we've asked for a range, we want to make sure that we only |
- // get that range if our current copy of the information is good. |
- // We shouldn't be asked to continue if we don't have a verifier. |
- DCHECK(params->offset() == 0 || has_etag || has_last_modified); |
- |
- if (params->offset() > 0) { |
- request->SetExtraRequestHeaderByName( |
- "Range", |
- base::StringPrintf("bytes=%" PRId64 "-", params->offset()), |
- true); |
- |
- if (has_last_modified) { |
- request->SetExtraRequestHeaderByName("If-Unmodified-Since", |
- params->last_modified(), |
- true); |
- } |
- if (has_etag) { |
- request->SetExtraRequestHeaderByName("If-Match", params->etag(), true); |
- } |
- } |
- |
- for (DownloadUrlParameters::RequestHeadersType::const_iterator iter |
- = params->request_headers_begin(); |
- iter != params->request_headers_end(); |
- ++iter) { |
- request->SetExtraRequestHeaderByName( |
- iter->first, iter->second, false/*overwrite*/); |
- } |
- |
- scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); |
- save_info->file_path = params->file_path(); |
- save_info->suggested_name = params->suggested_name(); |
- save_info->offset = params->offset(); |
- save_info->hash_state = params->hash_state(); |
- save_info->prompt_for_save_location = params->prompt(); |
- save_info->file_stream = params->GetFileStream(); |
- |
- ResourceDispatcherHost::Get()->BeginDownload( |
- request.Pass(), |
- params->referrer(), |
- params->content_initiated(), |
- params->resource_context(), |
- params->render_process_host_id(), |
- params->render_view_host_routing_id(), |
- params->prefer_cache(), |
- save_info.Pass(), |
- download_id, |
- params->callback()); |
-} |
- |
class MapValueIteratorAdapter { |
public: |
explicit MapValueIteratorAdapter( |
@@ -213,19 +129,6 @@ class DownloadItemFactoryImpl : public DownloadItemFactory { |
const net::BoundNetLog& bound_net_log) OVERRIDE { |
return new DownloadItemImpl(delegate, download_id, info, bound_net_log); |
} |
- |
- virtual DownloadItemImpl* CreateSavePageItem( |
- 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) OVERRIDE { |
- return new DownloadItemImpl(delegate, download_id, path, url, |
- mime_type, request_handle.Pass(), |
- bound_net_log); |
- } |
}; |
} // namespace |
@@ -249,7 +152,8 @@ DownloadManagerImpl::~DownloadManagerImpl() { |
} |
DownloadItemImpl* DownloadManagerImpl::CreateActiveItem( |
- uint32 id, const DownloadCreateInfo& info) { |
+ uint32 id, |
+ const DownloadCreateInfo& info) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DCHECK(!ContainsKey(downloads_, id)); |
net::BoundNetLog bound_net_log = |
@@ -356,54 +260,74 @@ void DownloadManagerImpl::Shutdown() { |
delegate_ = NULL; |
} |
-void DownloadManagerImpl::StartDownload( |
- scoped_ptr<DownloadCreateInfo> info, |
- scoped_ptr<ByteStreamReader> stream, |
- const DownloadUrlParameters::OnStartedCallback& on_started) { |
+void DownloadManagerImpl::StartDownloadWithActiveRequest( |
+ scoped_ptr<DownloadRequestHandle> request_handle, |
+ scoped_ptr<DownloadCreateInfo> info) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DCHECK(info); |
- uint32 download_id = info->download_id; |
- const bool new_download = (download_id == content::DownloadItem::kInvalidId); |
- base::Callback<void(uint32)> got_id(base::Bind( |
- &DownloadManagerImpl::StartDownloadWithId, |
- weak_factory_.GetWeakPtr(), |
- base::Passed(info.Pass()), |
- base::Passed(stream.Pass()), |
- on_started, |
- new_download)); |
- if (new_download) { |
- GetNextId(got_id); |
- } else { |
- got_id.Run(download_id); |
- } |
+ GetNextId(base::Bind(&DownloadManagerImpl::StartDownloadWithId, |
+ weak_factory_.GetWeakPtr(), |
+ base::Passed(&request_handle), |
+ base::Passed(&info))); |
} |
void DownloadManagerImpl::StartDownloadWithId( |
+ scoped_ptr<DownloadRequestHandle> request_handle, |
scoped_ptr<DownloadCreateInfo> info, |
- scoped_ptr<ByteStreamReader> stream, |
- const DownloadUrlParameters::OnStartedCallback& on_started, |
- bool new_download, |
uint32 id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK_NE(content::DownloadItem::kInvalidId, id); |
- DownloadItemImpl* download = NULL; |
- if (new_download) { |
- download = CreateActiveItem(id, *info); |
- } else { |
- DownloadMap::iterator item_iterator = downloads_.find(id); |
- // Trying to resume an interrupted download. |
- if (item_iterator == downloads_.end() || |
- (item_iterator->second->GetState() == DownloadItem::CANCELLED)) { |
- // If the download is no longer known to the DownloadManager, then it was |
- // removed after it was resumed. Ignore. If the download is cancelled |
- // while resuming, then also ignore the request. |
- info->request_handle.CancelRequest(); |
- if (!on_started.is_null()) |
- on_started.Run(NULL, net::ERR_ABORTED); |
- return; |
- } |
- download = item_iterator->second; |
- DCHECK_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
+ pending_requests_.push_back(request_handle.release()); |
+ OnDownloadRequestStarted(id, |
+ true /* new download */, |
+ DownloadUrlParameters::OnStartedCallback(), |
+ pending_requests_.back(), |
+ DOWNLOAD_INTERRUPT_REASON_NONE, |
+ info.Pass()); |
+} |
+ |
+DownloadItemImpl* DownloadManagerImpl::UpdateAndGetResumedDownloadItem( |
+ uint32 download_id, |
+ DownloadRequestHandle* request_handle, |
+ const DownloadCreateInfo& new_create_info) { |
+ DownloadMap::iterator item_iterator = downloads_.find(download_id); |
+ // Trying to resume an interrupted download. |
+ if (item_iterator == downloads_.end() || |
+ (item_iterator->second->GetState() == DownloadItem::CANCELLED)) { |
+ // If the download is no longer known to the DownloadManager, then it was |
+ // removed after it was resumed. Ignore. If the download is cancelled |
+ // while resuming, then also ignore the request. |
+ request_handle->CancelRequest(); |
+ return NULL; |
+ } |
+ DownloadItemImpl* download = item_iterator->second; |
+ DCHECK_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
+ download->MergeOriginInfoOnResume(new_create_info); |
+ return download; |
+} |
+ |
+void DownloadManagerImpl::OnDownloadRequestStarted( |
+ uint32 download_id, |
+ bool new_download, |
+ const DownloadUrlParameters::OnStartedCallback& on_started, |
+ DownloadRequestHandle* request_handle, |
+ DownloadInterruptReason interrupt_reason, |
+ scoped_ptr<DownloadCreateInfo> info) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK_NE(content::DownloadItem::kInvalidId, download_id); |
+ DCHECK(info); |
+ ScopedVector<DownloadRequestHandle>::iterator handle_iter = std::find( |
+ pending_requests_.begin(), pending_requests_.end(), request_handle); |
+ DCHECK(pending_requests_.end() != handle_iter); |
+ pending_requests_.weak_erase(handle_iter); |
+ scoped_ptr<DownloadRequestHandle> owned_request_handle(request_handle); |
+ DownloadItemImpl* download = |
+ new_download |
+ ? CreateActiveItem(download_id, *info) |
+ : UpdateAndGetResumedDownloadItem(download_id, request_handle, *info); |
+ if (!download) { |
+ if (!on_started.is_null()) |
+ on_started.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); |
+ return; |
} |
base::FilePath default_download_directory; |
@@ -416,12 +340,14 @@ void DownloadManagerImpl::StartDownloadWithId( |
// Create the download file and start the download. |
scoped_ptr<DownloadFile> download_file( |
- file_factory_->CreateFile( |
- info->save_info.Pass(), default_download_directory, |
- info->url(), info->referrer_url, |
- delegate_->GenerateFileHash(), |
- stream.Pass(), download->GetBoundNetLog(), |
- download->DestinationObserverAsWeakPtr())); |
+ file_factory_->CreateFile(info->save_info.Pass(), |
+ default_download_directory, |
+ info->url(), |
+ info->referrer_url, |
+ delegate_->GenerateFileHash(), |
+ info->stream_reader.Pass(), |
+ download->GetBoundNetLog(), |
+ download->DestinationObserverAsWeakPtr())); |
// Attach the client ID identifying the app to the AV system. |
if (download_file.get() && delegate_) { |
@@ -429,9 +355,7 @@ void DownloadManagerImpl::StartDownloadWithId( |
delegate_->ApplicationClientIdForFileScanning()); |
} |
- scoped_ptr<DownloadRequestHandleInterface> req_handle( |
- new DownloadRequestHandle(info->request_handle)); |
- download->Start(download_file.Pass(), req_handle.Pass()); |
+ download->Start(download_file.Pass(), owned_request_handle.Pass()); |
// For interrupted downloads, Start() will transition the state to |
// IN_PROGRESS and consumers will be notified via OnDownloadUpdated(). |
@@ -442,7 +366,7 @@ void DownloadManagerImpl::StartDownloadWithId( |
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); |
if (!on_started.is_null()) |
- on_started.Run(download, net::OK); |
+ on_started.Run(download, DOWNLOAD_INTERRUPT_REASON_NONE); |
} |
void DownloadManagerImpl::CheckForHistoryFilesRemoval() { |
@@ -466,6 +390,27 @@ void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) { |
} |
} |
+void DownloadManagerImpl::DownloadUrlWithId( |
+ scoped_ptr<DownloadUrlParameters> params, |
+ bool new_download, |
+ uint32 download_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK_NE(DownloadItem::kInvalidId, download_id); |
+ DownloadUrlParameters::OnStartedCallback on_started_callback = |
+ params->callback(); |
+ scoped_ptr<DownloadRequestHandle> request_handle( |
+ UrlDownloader::CreateDownloadRequest(params.Pass())); |
+ pending_requests_.push_back(request_handle.release()); |
+ DownloadRequestHandle::RequestStartedCallback started_callback = |
+ base::Bind(&DownloadManagerImpl::OnDownloadRequestStarted, |
+ weak_factory_.GetWeakPtr(), |
+ download_id, |
+ new_download, |
+ on_started_callback, |
+ pending_requests_.back()); |
+ pending_requests_.back()->Start(started_callback); |
+} |
+ |
void DownloadManagerImpl::OnFileExistenceChecked(uint32 download_id, |
bool result) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -480,47 +425,25 @@ BrowserContext* DownloadManagerImpl::GetBrowserContext() const { |
} |
void DownloadManagerImpl::CreateSavePackageDownloadItem( |
- const base::FilePath& main_file_path, |
- const GURL& page_url, |
- const std::string& mime_type, |
- scoped_ptr<DownloadRequestHandleInterface> request_handle, |
- const DownloadItemImplCreated& item_created) { |
+ scoped_ptr<DownloadCreateInfo> create_info, |
+ const DownloadItemImplCreated& download_created_callback) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- GetNextId(base::Bind( |
- &DownloadManagerImpl::CreateSavePackageDownloadItemWithId, |
- weak_factory_.GetWeakPtr(), |
- main_file_path, |
- page_url, |
- mime_type, |
- base::Passed(request_handle.Pass()), |
- item_created)); |
+ DCHECK(create_info->is_save_package_download); |
+ |
+ GetNextId( |
+ base::Bind(&DownloadManagerImpl::CreateSavePackageDownloadItemWithId, |
+ weak_factory_.GetWeakPtr(), |
+ base::Passed(&create_info), |
+ download_created_callback)); |
} |
void DownloadManagerImpl::CreateSavePackageDownloadItemWithId( |
- const base::FilePath& main_file_path, |
- const GURL& page_url, |
- const std::string& mime_type, |
- scoped_ptr<DownloadRequestHandleInterface> request_handle, |
- const DownloadItemImplCreated& item_created, |
+ scoped_ptr<DownloadCreateInfo> create_info, |
+ const DownloadItemImplCreated& download_created_callback, |
uint32 id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK_NE(content::DownloadItem::kInvalidId, id); |
- DCHECK(!ContainsKey(downloads_, id)); |
- net::BoundNetLog bound_net_log = |
- net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
- DownloadItemImpl* download_item = item_factory_->CreateSavePageItem( |
- this, |
- id, |
- main_file_path, |
- page_url, |
- mime_type, |
- request_handle.Pass(), |
- bound_net_log); |
- downloads_[download_item->GetId()] = download_item; |
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated( |
- this, download_item)); |
- if (!item_created.is_null()) |
- item_created.Run(download_item); |
+ DownloadItemImpl* item = CreateActiveItem(id, *create_info); |
+ download_created_callback.Run(item); |
} |
void DownloadManagerImpl::OnSavePackageSuccessfullyFinished( |
@@ -536,10 +459,7 @@ void DownloadManagerImpl::ResumeInterruptedDownload( |
scoped_ptr<content::DownloadUrlParameters> params, |
uint32 id) { |
RecordDownloadSource(INITIATED_BY_RESUMPTION); |
- BrowserThread::PostTask( |
- BrowserThread::IO, |
- FROM_HERE, |
- base::Bind(&BeginDownload, base::Passed(¶ms), id)); |
+ DownloadUrlWithId(params.Pass(), false /* new_download */, id); |
} |
void DownloadManagerImpl::SetDownloadItemFactoryForTesting( |
@@ -607,9 +527,11 @@ void DownloadManagerImpl::DownloadUrl( |
DCHECK(params->prefer_cache()); |
DCHECK(params->method() == "POST"); |
} |
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
- &BeginDownload, base::Passed(¶ms), |
- content::DownloadItem::kInvalidId)); |
+ |
+ GetNextId(base::Bind(&DownloadManagerImpl::DownloadUrlWithId, |
+ weak_factory_.GetWeakPtr(), |
+ base::Passed(¶ms), |
+ true /* new_download */)); |
} |
void DownloadManagerImpl::AddObserver(Observer* observer) { |