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(
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() {
#if defined(FULL_SAFE_BROWSING)
return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
......
......@@ -76,6 +76,11 @@ class ChromeDownloadManagerDelegate
bool ShouldOpenDownload(
download::DownloadItem* item,
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;
void GetSaveDir(content::BrowserContext* browser_context,
base::FilePath* website_save_dir,
......
......@@ -147,6 +147,10 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// Source ID generated for UKM.
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.
download::DownloadSource download_source = download::DownloadSource::UNKNOWN;
......
......@@ -489,6 +489,19 @@ void DownloadManagerImpl::Shutdown() {
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(
std::unique_ptr<DownloadCreateInfo> info,
std::unique_ptr<DownloadManager::InputStream> stream,
......@@ -496,6 +509,15 @@ void DownloadManagerImpl::StartDownload(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
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.
DCHECK((info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE &&
!stream->IsEmpty()) ||
......@@ -503,8 +525,6 @@ void DownloadManagerImpl::StartDownload(
stream->IsEmpty()));
DVLOG(20) << __func__ << "() result="
<< download::DownloadInterruptReasonToString(info->result);
uint32_t download_id = info->download_id;
const bool new_download = (download_id == download::DownloadItem::kInvalidId);
if (new_download)
RecordDownloadConnectionSecurity(info->url(), info->url_chain);
base::Callback<void(uint32_t)> got_id(base::Bind(
......@@ -790,6 +810,7 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
// Find a better way to create the DownloadResourceHandler instance.
std::unique_ptr<ResourceHandler> handler(
DownloadResourceHandler::CreateForNewRequest(url_request.get(),
params->request_origin(),
params->download_source()));
ResourceDispatcherHostImpl::Get()->BeginURLRequest(
......
......@@ -183,6 +183,10 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
const DownloadItemImplCreated& on_started,
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
// StartDownload() for testing.
DownloadItemImpl* CreateActiveItem(uint32_t id,
......
......@@ -145,6 +145,7 @@ DownloadRequestCore::DownloadRequestCore(
net::URLRequest* request,
Delegate* delegate,
bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source)
: delegate_(delegate),
request_(request),
......@@ -157,6 +158,7 @@ DownloadRequestCore::DownloadRequestCore(
is_partial_request_(false),
started_(false),
abort_reason_(download::DOWNLOAD_INTERRUPT_REASON_NONE),
request_origin_(request_origin),
download_source_(download_source) {
DCHECK(request_);
DCHECK(delegate_);
......@@ -229,6 +231,7 @@ DownloadRequestCore::CreateDownloadCreateInfo(
create_info->response_headers = request()->response_headers();
create_info->offset = create_info->save_info->offset;
create_info->fetch_error_body = fetch_error_body_;
create_info->request_origin = request_origin_;
create_info->download_source = download_source_;
return create_info;
}
......
......@@ -54,6 +54,7 @@ class CONTENT_EXPORT DownloadRequestCore
DownloadRequestCore(net::URLRequest* request,
Delegate* delegate,
bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source);
~DownloadRequestCore();
......@@ -159,6 +160,10 @@ class CONTENT_EXPORT DownloadRequestCore
// which is vague.
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.
download::DownloadSource download_source_;
......
......@@ -24,6 +24,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.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/render_frame_host.h"
#include "content/public/common/browser_side_navigation_policy.h"
......@@ -114,10 +115,11 @@ void DeleteOnUIThread(
DownloadResourceHandler::DownloadResourceHandler(
net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source)
: ResourceHandler(request),
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
// DownloadResourceHandler creation since the tab could be navigated
// before StartOnUIThread gets called. This is safe because deletion
......@@ -146,17 +148,18 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create(
net::URLRequest* request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler(
request, download::DownloadSource::NAVIGATION));
request, std::string(), download::DownloadSource::NAVIGATION));
return handler;
}
// static
std::unique_ptr<ResourceHandler> DownloadResourceHandler::CreateForNewRequest(
net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<ResourceHandler> handler(
new DownloadResourceHandler(request, download_source));
new DownloadResourceHandler(request, request_origin, download_source));
return handler;
}
......
......@@ -39,6 +39,7 @@ class CONTENT_EXPORT DownloadResourceHandler
// started_cb will be called exactly once on the UI thread.
// |id| should be invalid if the id should be automatically assigned.
DownloadResourceHandler(net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source);
// static
......@@ -55,6 +56,7 @@ class CONTENT_EXPORT DownloadResourceHandler
// navigation.
static std::unique_ptr<ResourceHandler> CreateForNewRequest(
net::URLRequest* request,
const std::string& request_origin,
download::DownloadSource download_source);
void OnRequestRedirected(
......
......@@ -54,6 +54,7 @@ DownloadResponseHandler::DownloadResponseHandler(
bool is_parallel_request,
bool is_transient,
bool fetch_error_body,
const std::string& request_origin,
download::DownloadSource download_source,
std::vector<GURL> url_chain)
: delegate_(delegate),
......@@ -64,6 +65,7 @@ DownloadResponseHandler::DownloadResponseHandler(
referrer_(resource_request->referrer),
is_transient_(is_transient),
fetch_error_body_(fetch_error_body),
request_origin_(request_origin),
download_source_(download_source),
has_strong_validators_(false),
is_partial_request_(save_info_->offset > 0),
......@@ -136,6 +138,7 @@ DownloadResponseHandler::CreateDownloadCreateInfo(
create_info->offset = create_info->save_info->offset;
create_info->mime_type = head.mime_type;
create_info->fetch_error_body = fetch_error_body_;
create_info->request_origin = request_origin_;
create_info->download_source = download_source_;
HandleResponseHeaders(head.headers.get(), create_info.get());
......
......@@ -41,6 +41,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient {
bool is_parallel_request,
bool is_transient,
bool fetch_error_body,
const std::string& request_origin,
download::DownloadSource download_source,
std::vector<GURL> url_chain);
~DownloadResponseHandler() override;
......@@ -82,6 +83,7 @@ class DownloadResponseHandler : public network::mojom::URLLoaderClient {
GURL referrer_;
bool is_transient_;
bool fetch_error_body_;
std::string request_origin_;
download::DownloadSource download_source_;
net::CertStatus cert_status_;
bool has_strong_validators_;
......
......@@ -155,6 +155,7 @@ void ResourceDownloader::Start(
download_url_parameters->GetSaveInfo()),
is_parallel_request, download_url_parameters->is_transient(),
download_url_parameters->fetch_error_body(),
download_url_parameters->request_origin(),
download_url_parameters->download_source(),
std::vector<GURL>(1, resource_request_->url));
network::mojom::URLLoaderClientPtr url_loader_client_ptr;
......@@ -192,7 +193,8 @@ void ResourceDownloader::InterceptResponse(
save_info->suggested_name = base::UTF8ToUTF16(suggested_filename.value());
url_loader_client_ = std::make_unique<DownloadResponseHandler>(
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.
net::SSLInfo info;
......
......@@ -82,7 +82,7 @@ std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
// |started_callback|.
std::unique_ptr<UrlDownloader> downloader(
new UrlDownloader(std::move(request), delegate, is_parallel_request,
params->download_source()));
params->request_origin(), params->download_source()));
downloader->Start();
return downloader;
......@@ -92,10 +92,15 @@ UrlDownloader::UrlDownloader(
std::unique_ptr<net::URLRequest> request,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source)
: request_(std::move(request)),
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) {}
UrlDownloader::~UrlDownloader() {
......
......@@ -28,6 +28,7 @@ class UrlDownloader : public net::URLRequest::Delegate,
UrlDownloader(std::unique_ptr<net::URLRequest> request,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
bool is_parallel_request,
const std::string& request_origin,
download::DownloadSource download_source);
~UrlDownloader() override;
......
......@@ -36,6 +36,14 @@ bool DownloadManagerDelegate::ShouldOpenDownload(
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(
download::DownloadItem* download) {
return true;
......
......@@ -122,6 +122,13 @@ class CONTENT_EXPORT DownloadManagerDelegate {
virtual bool ShouldOpenDownload(download::DownloadItem* item,
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.
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