Commit cba5d24a authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

Downloads : Added a delegate method for intercepting downloads

This method will be useful for other systems that want to handle
download themselves, especially offline pages, which can intercept
the download here onwards based on mime_type.

Bug: 802309
Change-Id: I5b7bfd7840334979d082c6afa983668ceb020968
Reviewed-on: https://chromium-review.googlesource.com/879548
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537008}
parent b23e6413
...@@ -513,6 +513,14 @@ bool ChromeDownloadManagerDelegate::ShouldOpenDownload( ...@@ -513,6 +513,14 @@ bool ChromeDownloadManagerDelegate::ShouldOpenDownload(
return true; return true;
} }
bool ChromeDownloadManagerDelegate::InterceptDownloadIfApplicable(
const GURL& url,
const std::string& mime_type,
const std::string& request_origin,
content::WebContents* web_contents) {
return false;
}
bool ChromeDownloadManagerDelegate::GenerateFileHash() { bool ChromeDownloadManagerDelegate::GenerateFileHash() {
#if defined(FULL_SAFE_BROWSING) #if defined(FULL_SAFE_BROWSING)
return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) && return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
......
...@@ -76,6 +76,11 @@ class ChromeDownloadManagerDelegate ...@@ -76,6 +76,11 @@ class ChromeDownloadManagerDelegate
bool ShouldOpenDownload( bool ShouldOpenDownload(
download::DownloadItem* item, download::DownloadItem* item,
const content::DownloadOpenDelayedCallback& callback) override; const content::DownloadOpenDelayedCallback& callback) override;
bool InterceptDownloadIfApplicable(
const GURL& url,
const std::string& mime_type,
const std::string& request_origin,
content::WebContents* web_contents) override;
bool GenerateFileHash() override; bool GenerateFileHash() override;
void GetSaveDir(content::BrowserContext* browser_context, void GetSaveDir(content::BrowserContext* browser_context,
base::FilePath* website_save_dir, base::FilePath* website_save_dir,
......
...@@ -147,6 +147,10 @@ struct CONTENT_EXPORT DownloadCreateInfo { ...@@ -147,6 +147,10 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// Source ID generated for UKM. // Source ID generated for UKM.
ukm::SourceId ukm_source_id; ukm::SourceId ukm_source_id;
// For downloads originating from custom tabs, this records the origin
// of the custom tab.
std::string request_origin;
// Source of the download, used in metrics. // Source of the download, used in metrics.
download::DownloadSource download_source = download::DownloadSource::UNKNOWN; download::DownloadSource download_source = download::DownloadSource::UNKNOWN;
......
...@@ -489,6 +489,19 @@ void DownloadManagerImpl::Shutdown() { ...@@ -489,6 +489,19 @@ void DownloadManagerImpl::Shutdown() {
delegate_ = nullptr; delegate_ = nullptr;
} }
bool DownloadManagerImpl::InterceptDownload(const DownloadCreateInfo& info) {
WebContents* web_contents =
info.request_handle ? info.request_handle->GetWebContents() : nullptr;
if (!delegate_ ||
!delegate_->InterceptDownloadIfApplicable(
info.url(), info.mime_type, info.request_origin, web_contents)) {
return false;
}
info.request_handle->CancelRequest(false);
return true;
}
void DownloadManagerImpl::StartDownload( void DownloadManagerImpl::StartDownload(
std::unique_ptr<DownloadCreateInfo> info, std::unique_ptr<DownloadCreateInfo> info,
std::unique_ptr<DownloadManager::InputStream> stream, std::unique_ptr<DownloadManager::InputStream> stream,
...@@ -496,6 +509,15 @@ void DownloadManagerImpl::StartDownload( ...@@ -496,6 +509,15 @@ void DownloadManagerImpl::StartDownload(
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(info); DCHECK(info);
uint32_t download_id = info->download_id;
bool new_download = (download_id == download::DownloadItem::kInvalidId);
if (new_download &&
info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE &&
InterceptDownload(*info)) {
GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
return;
}
// |stream| is only non-nil if the download request was successful. // |stream| is only non-nil if the download request was successful.
DCHECK((info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE && DCHECK((info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE &&
!stream->IsEmpty()) || !stream->IsEmpty()) ||
...@@ -503,8 +525,6 @@ void DownloadManagerImpl::StartDownload( ...@@ -503,8 +525,6 @@ void DownloadManagerImpl::StartDownload(
stream->IsEmpty())); stream->IsEmpty()));
DVLOG(20) << __func__ << "() result=" DVLOG(20) << __func__ << "() result="
<< download::DownloadInterruptReasonToString(info->result); << download::DownloadInterruptReasonToString(info->result);
uint32_t download_id = info->download_id;
const bool new_download = (download_id == download::DownloadItem::kInvalidId);
if (new_download) if (new_download)
RecordDownloadConnectionSecurity(info->url(), info->url_chain); RecordDownloadConnectionSecurity(info->url(), info->url_chain);
base::Callback<void(uint32_t)> got_id(base::Bind( base::Callback<void(uint32_t)> got_id(base::Bind(
...@@ -790,6 +810,7 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest( ...@@ -790,6 +810,7 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
// Find a better way to create the DownloadResourceHandler instance. // Find a better way to create the DownloadResourceHandler instance.
std::unique_ptr<ResourceHandler> handler( std::unique_ptr<ResourceHandler> handler(
DownloadResourceHandler::CreateForNewRequest(url_request.get(), DownloadResourceHandler::CreateForNewRequest(url_request.get(),
params->request_origin(),
params->download_source())); params->download_source()));
ResourceDispatcherHostImpl::Get()->BeginURLRequest( ResourceDispatcherHostImpl::Get()->BeginURLRequest(
......
...@@ -183,6 +183,10 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager, ...@@ -183,6 +183,10 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
const DownloadItemImplCreated& on_started, const DownloadItemImplCreated& on_started,
uint32_t id); uint32_t id);
// Intercepts the download to another system if applicable. Returns true if
// the download was intercepted.
bool InterceptDownload(const DownloadCreateInfo& info);
// Create a new active item based on the info. Separate from // Create a new active item based on the info. Separate from
// StartDownload() for testing. // StartDownload() for testing.
DownloadItemImpl* CreateActiveItem(uint32_t id, DownloadItemImpl* CreateActiveItem(uint32_t id,
......
...@@ -145,6 +145,7 @@ DownloadRequestCore::DownloadRequestCore( ...@@ -145,6 +145,7 @@ DownloadRequestCore::DownloadRequestCore(
net::URLRequest* request, net::URLRequest* request,
Delegate* delegate, Delegate* delegate,
bool is_parallel_request, bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source) download::DownloadSource download_source)
: delegate_(delegate), : delegate_(delegate),
request_(request), request_(request),
...@@ -157,6 +158,7 @@ DownloadRequestCore::DownloadRequestCore( ...@@ -157,6 +158,7 @@ DownloadRequestCore::DownloadRequestCore(
is_partial_request_(false), is_partial_request_(false),
started_(false), started_(false),
abort_reason_(download::DOWNLOAD_INTERRUPT_REASON_NONE), abort_reason_(download::DOWNLOAD_INTERRUPT_REASON_NONE),
request_origin_(request_origin),
download_source_(download_source) { download_source_(download_source) {
DCHECK(request_); DCHECK(request_);
DCHECK(delegate_); DCHECK(delegate_);
...@@ -229,6 +231,7 @@ DownloadRequestCore::CreateDownloadCreateInfo( ...@@ -229,6 +231,7 @@ DownloadRequestCore::CreateDownloadCreateInfo(
create_info->response_headers = request()->response_headers(); create_info->response_headers = request()->response_headers();
create_info->offset = create_info->save_info->offset; create_info->offset = create_info->save_info->offset;
create_info->fetch_error_body = fetch_error_body_; create_info->fetch_error_body = fetch_error_body_;
create_info->request_origin = request_origin_;
create_info->download_source = download_source_; create_info->download_source = download_source_;
return create_info; return create_info;
} }
......
...@@ -54,6 +54,7 @@ class CONTENT_EXPORT DownloadRequestCore ...@@ -54,6 +54,7 @@ class CONTENT_EXPORT DownloadRequestCore
DownloadRequestCore(net::URLRequest* request, DownloadRequestCore(net::URLRequest* request,
Delegate* delegate, Delegate* delegate,
bool is_parallel_request, bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source); download::DownloadSource download_source);
~DownloadRequestCore(); ~DownloadRequestCore();
...@@ -159,6 +160,10 @@ class CONTENT_EXPORT DownloadRequestCore ...@@ -159,6 +160,10 @@ class CONTENT_EXPORT DownloadRequestCore
// which is vague. // which is vague.
download::DownloadInterruptReason abort_reason_; download::DownloadInterruptReason abort_reason_;
// For downloads originating from custom tabs, this records the origin
// of the custom tab.
std::string request_origin_;
// Source of the download, used in metrics. // Source of the download, used in metrics.
download::DownloadSource download_source_; download::DownloadSource download_source_;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/browser_side_navigation_policy.h"
...@@ -114,10 +115,11 @@ void DeleteOnUIThread( ...@@ -114,10 +115,11 @@ void DeleteOnUIThread(
DownloadResourceHandler::DownloadResourceHandler( DownloadResourceHandler::DownloadResourceHandler(
net::URLRequest* request, net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source) download::DownloadSource download_source)
: ResourceHandler(request), : ResourceHandler(request),
tab_info_(new DownloadTabInfo()), tab_info_(new DownloadTabInfo()),
core_(request, this, false, download_source) { core_(request, this, false, request_origin, download_source) {
// Do UI thread initialization for tab_info_ asap after // Do UI thread initialization for tab_info_ asap after
// DownloadResourceHandler creation since the tab could be navigated // DownloadResourceHandler creation since the tab could be navigated
// before StartOnUIThread gets called. This is safe because deletion // before StartOnUIThread gets called. This is safe because deletion
...@@ -146,17 +148,18 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create( ...@@ -146,17 +148,18 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create(
net::URLRequest* request) { net::URLRequest* request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler( std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler(
request, download::DownloadSource::NAVIGATION)); request, std::string(), download::DownloadSource::NAVIGATION));
return handler; return handler;
} }
// static // static
std::unique_ptr<ResourceHandler> DownloadResourceHandler::CreateForNewRequest( std::unique_ptr<ResourceHandler> DownloadResourceHandler::CreateForNewRequest(
net::URLRequest* request, net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source) { download::DownloadSource download_source) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<ResourceHandler> handler( std::unique_ptr<ResourceHandler> handler(
new DownloadResourceHandler(request, download_source)); new DownloadResourceHandler(request, request_origin, download_source));
return handler; return handler;
} }
......
...@@ -39,6 +39,7 @@ class CONTENT_EXPORT DownloadResourceHandler ...@@ -39,6 +39,7 @@ class CONTENT_EXPORT DownloadResourceHandler
// started_cb will be called exactly once on the UI thread. // started_cb will be called exactly once on the UI thread.
// |id| should be invalid if the id should be automatically assigned. // |id| should be invalid if the id should be automatically assigned.
DownloadResourceHandler(net::URLRequest* request, DownloadResourceHandler(net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source); download::DownloadSource download_source);
// static // static
...@@ -55,6 +56,7 @@ class CONTENT_EXPORT DownloadResourceHandler ...@@ -55,6 +56,7 @@ class CONTENT_EXPORT DownloadResourceHandler
// navigation. // navigation.
static std::unique_ptr<ResourceHandler> CreateForNewRequest( static std::unique_ptr<ResourceHandler> CreateForNewRequest(
net::URLRequest* request, net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source); download::DownloadSource download_source);
void OnRequestRedirected( void OnRequestRedirected(
......
...@@ -54,6 +54,7 @@ DownloadResponseHandler::DownloadResponseHandler( ...@@ -54,6 +54,7 @@ DownloadResponseHandler::DownloadResponseHandler(
bool is_parallel_request, bool is_parallel_request,
bool is_transient, bool is_transient,
bool fetch_error_body, bool fetch_error_body,
const std::string& request_origin,
download::DownloadSource download_source, download::DownloadSource download_source,
std::vector<GURL> url_chain) std::vector<GURL> url_chain)
: delegate_(delegate), : delegate_(delegate),
...@@ -64,6 +65,7 @@ DownloadResponseHandler::DownloadResponseHandler( ...@@ -64,6 +65,7 @@ DownloadResponseHandler::DownloadResponseHandler(
referrer_(resource_request->referrer), referrer_(resource_request->referrer),
is_transient_(is_transient), is_transient_(is_transient),
fetch_error_body_(fetch_error_body), fetch_error_body_(fetch_error_body),
request_origin_(request_origin),
download_source_(download_source), download_source_(download_source),
has_strong_validators_(false), has_strong_validators_(false),
is_partial_request_(save_info_->offset > 0), is_partial_request_(save_info_->offset > 0),
...@@ -136,6 +138,7 @@ DownloadResponseHandler::CreateDownloadCreateInfo( ...@@ -136,6 +138,7 @@ DownloadResponseHandler::CreateDownloadCreateInfo(
create_info->offset = create_info->save_info->offset; create_info->offset = create_info->save_info->offset;
create_info->mime_type = head.mime_type; create_info->mime_type = head.mime_type;
create_info->fetch_error_body = fetch_error_body_; create_info->fetch_error_body = fetch_error_body_;
create_info->request_origin = request_origin_;
create_info->download_source = download_source_; create_info->download_source = download_source_;
HandleResponseHeaders(head.headers.get(), create_info.get()); HandleResponseHeaders(head.headers.get(), create_info.get());
......
...@@ -41,6 +41,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient { ...@@ -41,6 +41,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient {
bool is_parallel_request, bool is_parallel_request,
bool is_transient, bool is_transient,
bool fetch_error_body, bool fetch_error_body,
const std::string& request_origin,
download::DownloadSource download_source, download::DownloadSource download_source,
std::vector<GURL> url_chain); std::vector<GURL> url_chain);
~DownloadResponseHandler() override; ~DownloadResponseHandler() override;
...@@ -82,6 +83,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient { ...@@ -82,6 +83,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient {
GURL referrer_; GURL referrer_;
bool is_transient_; bool is_transient_;
bool fetch_error_body_; bool fetch_error_body_;
std::string request_origin_;
download::DownloadSource download_source_; download::DownloadSource download_source_;
net::CertStatus cert_status_; net::CertStatus cert_status_;
bool has_strong_validators_; bool has_strong_validators_;
......
...@@ -155,6 +155,7 @@ void ResourceDownloader::Start( ...@@ -155,6 +155,7 @@ void ResourceDownloader::Start(
download_url_parameters->GetSaveInfo()), download_url_parameters->GetSaveInfo()),
is_parallel_request, download_url_parameters->is_transient(), is_parallel_request, download_url_parameters->is_transient(),
download_url_parameters->fetch_error_body(), download_url_parameters->fetch_error_body(),
download_url_parameters->request_origin(),
download_url_parameters->download_source(), download_url_parameters->download_source(),
std::vector<GURL>(1, resource_request_->url)); std::vector<GURL>(1, resource_request_->url));
network::mojom::URLLoaderClientPtr url_loader_client_ptr; network::mojom::URLLoaderClientPtr url_loader_client_ptr;
...@@ -192,7 +193,8 @@ void ResourceDownloader::InterceptResponse( ...@@ -192,7 +193,8 @@ void ResourceDownloader::InterceptResponse(
save_info->suggested_name = base::UTF8ToUTF16(suggested_filename.value()); save_info->suggested_name = base::UTF8ToUTF16(suggested_filename.value());
url_loader_client_ = std::make_unique<DownloadResponseHandler>( url_loader_client_ = std::make_unique<DownloadResponseHandler>(
resource_request_.get(), this, std::move(save_info), false, false, false, resource_request_.get(), this, std::move(save_info), false, false, false,
download::DownloadSource::NAVIGATION, std::move(url_chain)); std::string(), download::DownloadSource::NAVIGATION,
std::move(url_chain));
// Simulate on the new URLLoaderClient calls that happened on the old client. // Simulate on the new URLLoaderClient calls that happened on the old client.
net::SSLInfo info; net::SSLInfo info;
......
...@@ -82,7 +82,7 @@ std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload( ...@@ -82,7 +82,7 @@ std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
// |started_callback|. // |started_callback|.
std::unique_ptr<UrlDownloader> downloader( std::unique_ptr<UrlDownloader> downloader(
new UrlDownloader(std::move(request), delegate, is_parallel_request, new UrlDownloader(std::move(request), delegate, is_parallel_request,
params->download_source())); params->request_origin(), params->download_source()));
downloader->Start(); downloader->Start();
return downloader; return downloader;
...@@ -92,10 +92,15 @@ UrlDownloader::UrlDownloader( ...@@ -92,10 +92,15 @@ UrlDownloader::UrlDownloader(
std::unique_ptr<net::URLRequest> request, std::unique_ptr<net::URLRequest> request,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate, base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
bool is_parallel_request, bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source) download::DownloadSource download_source)
: request_(std::move(request)), : request_(std::move(request)),
delegate_(delegate), delegate_(delegate),
core_(request_.get(), this, is_parallel_request, download_source), core_(request_.get(),
this,
is_parallel_request,
request_origin,
download_source),
weak_ptr_factory_(this) {} weak_ptr_factory_(this) {}
UrlDownloader::~UrlDownloader() { UrlDownloader::~UrlDownloader() {
......
...@@ -28,6 +28,7 @@ class UrlDownloader : public net::URLRequest::Delegate, ...@@ -28,6 +28,7 @@ class UrlDownloader : public net::URLRequest::Delegate,
UrlDownloader(std::unique_ptr<net::URLRequest> request, UrlDownloader(std::unique_ptr<net::URLRequest> request,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate, base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
bool is_parallel_request, bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source); download::DownloadSource download_source);
~UrlDownloader() override; ~UrlDownloader() override;
......
...@@ -36,6 +36,14 @@ bool DownloadManagerDelegate::ShouldOpenDownload( ...@@ -36,6 +36,14 @@ bool DownloadManagerDelegate::ShouldOpenDownload(
return true; return true;
} }
bool DownloadManagerDelegate::InterceptDownloadIfApplicable(
const GURL& url,
const std::string& mime_type,
const std::string& request_origin,
WebContents* web_contents) {
return false;
}
bool DownloadManagerDelegate::IsMostRecentDownloadItemAtFilePath( bool DownloadManagerDelegate::IsMostRecentDownloadItemAtFilePath(
download::DownloadItem* download) { download::DownloadItem* download) {
return true; return true;
......
...@@ -122,6 +122,13 @@ class CONTENT_EXPORT DownloadManagerDelegate { ...@@ -122,6 +122,13 @@ class CONTENT_EXPORT DownloadManagerDelegate {
virtual bool ShouldOpenDownload(download::DownloadItem* item, virtual bool ShouldOpenDownload(download::DownloadItem* item,
const DownloadOpenDelayedCallback& callback); const DownloadOpenDelayedCallback& callback);
// Checks and hands off the downloading to be handled by another system based
// on mime type. Returns true if the download was intercepted.
virtual bool InterceptDownloadIfApplicable(const GURL& url,
const std::string& mime_type,
const std::string& request_origin,
WebContents* web_contents);
// Returns true if we need to generate a binary hash for downloads. // Returns true if we need to generate a binary hash for downloads.
virtual bool GenerateFileHash(); virtual bool GenerateFileHash();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment