Add permission callback for user-initated downloads (fixes issue #3183)
This change adds a CefDownloadHandler::CanDownload callback for optionally blocking user-initiated downloads (e.g. alt + link click or link click that returns a `Content-Disposition: attachment` response from the server). To test: - Run `ceftests --gtest_filter=DownloadTest.*`. - Run `cefclient --hide-controls`. User-initiated downloads will be blocked.
This commit is contained in:
parent
2f5838eaaa
commit
6d7a680187
|
@ -33,7 +33,7 @@
|
||||||
// by hand. See the translator.README.txt file in the tools directory for
|
// by hand. See the translator.README.txt file in the tools directory for
|
||||||
// more information.
|
// more information.
|
||||||
//
|
//
|
||||||
// $hash=ec13ec3e2819e4ac49792c3a1c57bc60b45fb95b$
|
// $hash=33862915eb4156a70794a346a090154c468763e2$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_
|
#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_
|
||||||
|
@ -103,6 +103,18 @@ typedef struct _cef_download_handler_t {
|
||||||
///
|
///
|
||||||
cef_base_ref_counted_t base;
|
cef_base_ref_counted_t base;
|
||||||
|
|
||||||
|
///
|
||||||
|
// Called before a download begins in response to a user-initiated action
|
||||||
|
// (e.g. alt + link click or link click that returns a `Content-Disposition:
|
||||||
|
// attachment` response from the server). |url| is the target download URL and
|
||||||
|
// |request_function| is the target function (GET, POST, etc). Return true (1)
|
||||||
|
// to proceed with the download or false (0) to cancel the download.
|
||||||
|
///
|
||||||
|
int(CEF_CALLBACK* can_download)(struct _cef_download_handler_t* self,
|
||||||
|
struct _cef_browser_t* browser,
|
||||||
|
const cef_string_t* url,
|
||||||
|
const cef_string_t* request_method);
|
||||||
|
|
||||||
///
|
///
|
||||||
// Called before a download begins. |suggested_name| is the suggested name for
|
// Called before a download begins. |suggested_name| is the suggested name for
|
||||||
// the download file. By default the download will be canceled. Execute
|
// the download file. By default the download will be canceled. Execute
|
||||||
|
|
|
@ -42,13 +42,13 @@
|
||||||
// way that may cause binary incompatibility with other builds. The universal
|
// way that may cause binary incompatibility with other builds. The universal
|
||||||
// hash value will change if any platform is affected whereas the platform hash
|
// hash value will change if any platform is affected whereas the platform hash
|
||||||
// values will change only if that particular platform is affected.
|
// values will change only if that particular platform is affected.
|
||||||
#define CEF_API_HASH_UNIVERSAL "099de505181a68d5b53885e57d91ae0276259bfa"
|
#define CEF_API_HASH_UNIVERSAL "e42afcebc271841716a6f3197194e3ea02d037cb"
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#define CEF_API_HASH_PLATFORM "0887a2a4ef42c8e2e33aba6662d2891f020e810a"
|
#define CEF_API_HASH_PLATFORM "e08d5cc79cedebc94efc39536c27b6c30d24c9df"
|
||||||
#elif defined(OS_MAC)
|
#elif defined(OS_MAC)
|
||||||
#define CEF_API_HASH_PLATFORM "3d220485ac3df3a74e15db819ea16c98f78116ae"
|
#define CEF_API_HASH_PLATFORM "86626c6c27b29841a4bf01c145e2d7990a73abf0"
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
#define CEF_API_HASH_PLATFORM "ee08ceb06c69dac1ac16361daabe3378c9d2d621"
|
#define CEF_API_HASH_PLATFORM "a19b7983d07d0e6afe0ae46c1768111078995c5e"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -90,6 +90,20 @@ class CefDownloadItemCallback : public virtual CefBaseRefCounted {
|
||||||
/*--cef(source=client)--*/
|
/*--cef(source=client)--*/
|
||||||
class CefDownloadHandler : public virtual CefBaseRefCounted {
|
class CefDownloadHandler : public virtual CefBaseRefCounted {
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
// Called before a download begins in response to a user-initiated action
|
||||||
|
// (e.g. alt + link click or link click that returns a `Content-Disposition:
|
||||||
|
// attachment` response from the server). |url| is the target download URL and
|
||||||
|
// |request_method| is the target method (GET, POST, etc). Return true to
|
||||||
|
// proceed with the download or false to cancel the download.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
virtual bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
// Called before a download begins. |suggested_name| is the suggested name for
|
// Called before a download begins. |suggested_name| is the suggested name for
|
||||||
// the download file. By default the download will be canceled. Execute
|
// the download file. By default the download will be canceled. Execute
|
||||||
|
|
|
@ -1225,6 +1225,13 @@ bool AlloyBrowserHostImpl::HandleContextMenu(
|
||||||
return HandleContextMenu(web_contents(), params);
|
return HandleContextMenu(web_contents(), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AlloyBrowserHostImpl::CanDownload(
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) {
|
||||||
|
contents_delegate_->CanDownload(url, request_method, std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardEventProcessingResult AlloyBrowserHostImpl::PreHandleKeyboardEvent(
|
KeyboardEventProcessingResult AlloyBrowserHostImpl::PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
|
|
@ -225,6 +225,9 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
||||||
bool TakeFocus(content::WebContents* source, bool reverse) override;
|
bool TakeFocus(content::WebContents* source, bool reverse) override;
|
||||||
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||||
const content::ContextMenuParams& params) override;
|
const content::ContextMenuParams& params) override;
|
||||||
|
void CanDownload(const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) override;
|
||||||
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
|
|
@ -180,6 +180,23 @@ void CefBrowserContentsDelegate::ExitFullscreenModeForTab(
|
||||||
OnFullscreenModeChange(/*fullscreen=*/false);
|
OnFullscreenModeChange(/*fullscreen=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefBrowserContentsDelegate::CanDownload(
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) {
|
||||||
|
bool allow = true;
|
||||||
|
|
||||||
|
if (auto delegate = platform_delegate()) {
|
||||||
|
if (auto c = client()) {
|
||||||
|
if (auto handler = c->GetDownloadHandler()) {
|
||||||
|
allow = handler->CanDownload(browser(), url.spec(), request_method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::move(callback).Run(allow);
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardEventProcessingResult
|
KeyboardEventProcessingResult
|
||||||
CefBrowserContentsDelegate::PreHandleKeyboardEvent(
|
CefBrowserContentsDelegate::PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
|
|
|
@ -101,6 +101,9 @@ class CefBrowserContentsDelegate : public content::WebContentsDelegate,
|
||||||
content::RenderFrameHost* requesting_frame,
|
content::RenderFrameHost* requesting_frame,
|
||||||
const blink::mojom::FullscreenOptions& options) override;
|
const blink::mojom::FullscreenOptions& options) override;
|
||||||
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
||||||
|
void CanDownload(const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) override;
|
||||||
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
|
|
@ -235,6 +235,20 @@ void ChromeBrowserDelegate::ExitFullscreenModeForTab(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChromeBrowserDelegate::CanDownload(
|
||||||
|
const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) {
|
||||||
|
auto source = browser_->tab_strip_model()->GetActiveWebContents();
|
||||||
|
DCHECK(source);
|
||||||
|
|
||||||
|
if (auto delegate = GetDelegateForWebContents(source)) {
|
||||||
|
delegate->CanDownload(url, request_method, std::move(callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::move(callback).Run(true);
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardEventProcessingResult ChromeBrowserDelegate::PreHandleKeyboardEvent(
|
KeyboardEventProcessingResult ChromeBrowserDelegate::PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
|
|
@ -86,6 +86,9 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
|
||||||
content::RenderFrameHost* requesting_frame,
|
content::RenderFrameHost* requesting_frame,
|
||||||
const blink::mojom::FullscreenOptions& options) override;
|
const blink::mojom::FullscreenOptions& options) override;
|
||||||
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
|
||||||
|
void CanDownload(const GURL& url,
|
||||||
|
const std::string& request_method,
|
||||||
|
base::OnceCallback<void(bool)> callback) override;
|
||||||
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=496b226297ba7d5fa5e7e7bd4117c417e26fae59$
|
// $hash=89f651178065dbc03e70e763085bf9125dda6640$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
|
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
|
||||||
|
@ -23,6 +23,40 @@ namespace {
|
||||||
|
|
||||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
|
int CEF_CALLBACK
|
||||||
|
download_handler_can_download(struct _cef_download_handler_t* self,
|
||||||
|
cef_browser_t* browser,
|
||||||
|
const cef_string_t* url,
|
||||||
|
const cef_string_t* request_method) {
|
||||||
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
|
DCHECK(self);
|
||||||
|
if (!self)
|
||||||
|
return 0;
|
||||||
|
// Verify param: browser; type: refptr_diff
|
||||||
|
DCHECK(browser);
|
||||||
|
if (!browser)
|
||||||
|
return 0;
|
||||||
|
// Verify param: url; type: string_byref_const
|
||||||
|
DCHECK(url);
|
||||||
|
if (!url)
|
||||||
|
return 0;
|
||||||
|
// Verify param: request_method; type: string_byref_const
|
||||||
|
DCHECK(request_method);
|
||||||
|
if (!request_method)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
bool _retval = CefDownloadHandlerCppToC::Get(self)->CanDownload(
|
||||||
|
CefBrowserCToCpp::Wrap(browser), CefString(url),
|
||||||
|
CefString(request_method));
|
||||||
|
|
||||||
|
// Return type: bool
|
||||||
|
return _retval;
|
||||||
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK
|
void CEF_CALLBACK
|
||||||
download_handler_on_before_download(struct _cef_download_handler_t* self,
|
download_handler_on_before_download(struct _cef_download_handler_t* self,
|
||||||
cef_browser_t* browser,
|
cef_browser_t* browser,
|
||||||
|
@ -97,6 +131,7 @@ download_handler_on_download_updated(struct _cef_download_handler_t* self,
|
||||||
// CONSTRUCTOR - Do not edit by hand.
|
// CONSTRUCTOR - Do not edit by hand.
|
||||||
|
|
||||||
CefDownloadHandlerCppToC::CefDownloadHandlerCppToC() {
|
CefDownloadHandlerCppToC::CefDownloadHandlerCppToC() {
|
||||||
|
GetStruct()->can_download = download_handler_can_download;
|
||||||
GetStruct()->on_before_download = download_handler_on_before_download;
|
GetStruct()->on_before_download = download_handler_on_before_download;
|
||||||
GetStruct()->on_download_updated = download_handler_on_download_updated;
|
GetStruct()->on_download_updated = download_handler_on_download_updated;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=c4e47ffd023b528b9c5b658126f4a1d9fd05cf98$
|
// $hash=bb3a8a9a02dc3d2e4bdf0e926f61adc05e3af351$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
|
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
|
||||||
|
@ -21,6 +21,40 @@
|
||||||
|
|
||||||
// VIRTUAL METHODS - Body may be edited by hand.
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
|
NO_SANITIZE("cfi-icall")
|
||||||
|
bool CefDownloadHandlerCToCpp::CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) {
|
||||||
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
|
cef_download_handler_t* _struct = GetStruct();
|
||||||
|
if (CEF_MEMBER_MISSING(_struct, can_download))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
|
// Verify param: browser; type: refptr_diff
|
||||||
|
DCHECK(browser.get());
|
||||||
|
if (!browser.get())
|
||||||
|
return false;
|
||||||
|
// Verify param: url; type: string_byref_const
|
||||||
|
DCHECK(!url.empty());
|
||||||
|
if (url.empty())
|
||||||
|
return false;
|
||||||
|
// Verify param: request_method; type: string_byref_const
|
||||||
|
DCHECK(!request_method.empty());
|
||||||
|
if (request_method.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
int _retval =
|
||||||
|
_struct->can_download(_struct, CefBrowserCppToC::Wrap(browser),
|
||||||
|
url.GetStruct(), request_method.GetStruct());
|
||||||
|
|
||||||
|
// Return type: bool
|
||||||
|
return _retval ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
NO_SANITIZE("cfi-icall")
|
NO_SANITIZE("cfi-icall")
|
||||||
void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=172a12dd9e68b65afff9eef5b93f0e480beaf904$
|
// $hash=fa32af3253cface693ec3ef420863852f5c68379$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
|
||||||
|
@ -35,6 +35,9 @@ class CefDownloadHandlerCToCpp
|
||||||
virtual ~CefDownloadHandlerCToCpp();
|
virtual ~CefDownloadHandlerCToCpp();
|
||||||
|
|
||||||
// CefDownloadHandler methods.
|
// CefDownloadHandler methods.
|
||||||
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) override;
|
||||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
|
|
|
@ -13,7 +13,7 @@ index 9e534ff1683f1..de406f5879be0 100644
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
||||||
index 04e327d970b87..6bd83131116d9 100644
|
index 04e327d970b87..f79b861fe6966 100644
|
||||||
--- chrome/browser/ui/browser.cc
|
--- chrome/browser/ui/browser.cc
|
||||||
+++ chrome/browser/ui/browser.cc
|
+++ chrome/browser/ui/browser.cc
|
||||||
@@ -262,6 +262,25 @@
|
@@ -262,6 +262,25 @@
|
||||||
|
@ -159,7 +159,27 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
void Browser::ContentsMouseEvent(WebContents* source,
|
void Browser::ContentsMouseEvent(WebContents* source,
|
||||||
bool motion,
|
bool motion,
|
||||||
bool exited) {
|
bool exited) {
|
||||||
@@ -1807,6 +1883,10 @@ void Browser::WebContentsCreated(WebContents* source_contents,
|
@@ -1715,6 +1791,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void Browser::CanDownload(const GURL& url,
|
||||||
|
+ const std::string& request_method,
|
||||||
|
+ base::OnceCallback<void(bool)> callback) {
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ if (cef_browser_delegate_) {
|
||||||
|
+ cef_browser_delegate_->CanDownload(url, request_method,
|
||||||
|
+ std::move(callback));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ std::move(callback).Run(true);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void Browser::BeforeUnloadFired(WebContents* web_contents,
|
||||||
|
bool proceed,
|
||||||
|
bool* proceed_to_fire_unload) {
|
||||||
|
@@ -1807,6 +1896,10 @@ void Browser::WebContentsCreated(WebContents* source_contents,
|
||||||
|
|
||||||
// Make the tab show up in the task manager.
|
// Make the tab show up in the task manager.
|
||||||
task_manager::WebContentsTags::CreateForTabContents(new_contents);
|
task_manager::WebContentsTags::CreateForTabContents(new_contents);
|
||||||
|
@ -170,7 +190,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::PortalWebContentsCreated(WebContents* portal_web_contents) {
|
void Browser::PortalWebContentsCreated(WebContents* portal_web_contents) {
|
||||||
@@ -1851,6 +1931,8 @@ void Browser::RendererResponsive(
|
@@ -1851,6 +1944,8 @@ void Browser::RendererResponsive(
|
||||||
void Browser::DidNavigatePrimaryMainFramePostCommit(WebContents* web_contents) {
|
void Browser::DidNavigatePrimaryMainFramePostCommit(WebContents* web_contents) {
|
||||||
if (web_contents == tab_strip_model_->GetActiveWebContents())
|
if (web_contents == tab_strip_model_->GetActiveWebContents())
|
||||||
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE);
|
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE);
|
||||||
|
@ -179,7 +199,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
}
|
}
|
||||||
|
|
||||||
content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
|
content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
|
||||||
@@ -1906,11 +1988,15 @@ void Browser::EnterFullscreenModeForTab(
|
@@ -1906,11 +2001,15 @@ void Browser::EnterFullscreenModeForTab(
|
||||||
const blink::mojom::FullscreenOptions& options) {
|
const blink::mojom::FullscreenOptions& options) {
|
||||||
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
|
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
|
||||||
requesting_frame, options.display_id);
|
requesting_frame, options.display_id);
|
||||||
|
@ -195,7 +215,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
|
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
|
||||||
@@ -2620,13 +2706,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
|
@@ -2620,13 +2719,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
|
||||||
// Browser, Getters for UI (private):
|
// Browser, Getters for UI (private):
|
||||||
|
|
||||||
StatusBubble* Browser::GetStatusBubble() {
|
StatusBubble* Browser::GetStatusBubble() {
|
||||||
|
@ -217,7 +237,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
return window_ ? window_->GetStatusBubble() : nullptr;
|
return window_ ? window_->GetStatusBubble() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2753,6 +2846,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
|
@@ -2753,6 +2859,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
|
||||||
content_translate_driver->RemoveTranslationObserver(this);
|
content_translate_driver->RemoveTranslationObserver(this);
|
||||||
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
|
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +247,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
||||||
|
|
||||||
void Browser::TabDetachedAtImpl(content::WebContents* contents,
|
void Browser::TabDetachedAtImpl(content::WebContents* contents,
|
||||||
diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h
|
diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h
|
||||||
index a63ba24be314e..38a6dcbf034ef 100644
|
index a63ba24be314e..8eb344f1daeb8 100644
|
||||||
--- chrome/browser/ui/browser.h
|
--- chrome/browser/ui/browser.h
|
||||||
+++ chrome/browser/ui/browser.h
|
+++ chrome/browser/ui/browser.h
|
||||||
@@ -21,6 +21,7 @@
|
@@ -21,6 +21,7 @@
|
||||||
|
@ -288,7 +308,7 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
||||||
// Get the FindBarController for this browser, creating it if it does not
|
// Get the FindBarController for this browser, creating it if it does not
|
||||||
// yet exist.
|
// yet exist.
|
||||||
FindBarController* GetFindBarController();
|
FindBarController* GetFindBarController();
|
||||||
@@ -794,6 +817,11 @@ class Browser : public TabStripModelObserver,
|
@@ -794,11 +817,19 @@ class Browser : public TabStripModelObserver,
|
||||||
void SetContentsBounds(content::WebContents* source,
|
void SetContentsBounds(content::WebContents* source,
|
||||||
const gfx::Rect& bounds) override;
|
const gfx::Rect& bounds) override;
|
||||||
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
||||||
|
@ -300,7 +320,15 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
||||||
void ContentsMouseEvent(content::WebContents* source,
|
void ContentsMouseEvent(content::WebContents* source,
|
||||||
bool motion,
|
bool motion,
|
||||||
bool exited) override;
|
bool exited) override;
|
||||||
@@ -1196,6 +1224,8 @@ class Browser : public TabStripModelObserver,
|
void ContentsZoomChange(bool zoom_in) override;
|
||||||
|
bool TakeFocus(content::WebContents* source, bool reverse) override;
|
||||||
|
+ void CanDownload(const GURL& url,
|
||||||
|
+ const std::string& request_method,
|
||||||
|
+ base::OnceCallback<void(bool)> callback) override;
|
||||||
|
void BeforeUnloadFired(content::WebContents* source,
|
||||||
|
bool proceed,
|
||||||
|
bool* proceed_to_fire_unload) override;
|
||||||
|
@@ -1196,6 +1227,8 @@ class Browser : public TabStripModelObserver,
|
||||||
const std::string initial_workspace_;
|
const std::string initial_workspace_;
|
||||||
bool initial_visible_on_all_workspaces_state_;
|
bool initial_visible_on_all_workspaces_state_;
|
||||||
|
|
||||||
|
@ -309,7 +337,7 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
||||||
CreationSource creation_source_ = CreationSource::kUnknown;
|
CreationSource creation_source_ = CreationSource::kUnknown;
|
||||||
|
|
||||||
UnloadController unload_controller_;
|
UnloadController unload_controller_;
|
||||||
@@ -1257,6 +1287,10 @@ class Browser : public TabStripModelObserver,
|
@@ -1257,6 +1290,10 @@ class Browser : public TabStripModelObserver,
|
||||||
extension_browser_window_helper_;
|
extension_browser_window_helper_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -515,6 +515,21 @@ bool ClientHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||||
return mouse_cursor_change_disabled_;
|
return mouse_cursor_change_disabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClientHandler::CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
if (!with_controls_) {
|
||||||
|
// Block the download.
|
||||||
|
LOG(INFO) << "Blocking download";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the download.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ClientHandler::OnBeforeDownload(
|
void ClientHandler::OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
|
|
|
@ -170,6 +170,9 @@ class ClientHandler : public CefClient,
|
||||||
const CefCursorInfo& custom_cursor_info) override;
|
const CefCursorInfo& custom_cursor_info) override;
|
||||||
|
|
||||||
// CefDownloadHandler methods
|
// CefDownloadHandler methods
|
||||||
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) override;
|
||||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
|
|
|
@ -169,11 +169,12 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
||||||
class DownloadTestHandler : public TestHandler {
|
class DownloadTestHandler : public TestHandler {
|
||||||
public:
|
public:
|
||||||
enum TestMode {
|
enum TestMode {
|
||||||
PROGAMMATIC,
|
PROGRAMMATIC,
|
||||||
NAVIGATED,
|
NAVIGATED,
|
||||||
PENDING,
|
PENDING,
|
||||||
CLICKED,
|
CLICKED,
|
||||||
CLICKED_REJECTED,
|
CLICKED_INVALID,
|
||||||
|
CLICKED_BLOCKED,
|
||||||
};
|
};
|
||||||
|
|
||||||
DownloadTestHandler(TestMode test_mode,
|
DownloadTestHandler(TestMode test_mode,
|
||||||
|
@ -186,7 +187,15 @@ class DownloadTestHandler : public TestHandler {
|
||||||
verified_results_(false) {}
|
verified_results_(false) {}
|
||||||
|
|
||||||
bool is_clicked() const {
|
bool is_clicked() const {
|
||||||
return test_mode_ == CLICKED || test_mode_ == CLICKED_REJECTED;
|
return test_mode_ == CLICKED || test_mode_ == CLICKED_INVALID ||
|
||||||
|
test_mode_ == CLICKED_BLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_clicked_and_downloaded() const { return test_mode_ == CLICKED; }
|
||||||
|
|
||||||
|
bool is_downloaded() const {
|
||||||
|
return test_mode_ == PROGRAMMATIC || test_mode_ == NAVIGATED ||
|
||||||
|
is_clicked_and_downloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunTest() override {
|
void RunTest() override {
|
||||||
|
@ -212,7 +221,7 @@ class DownloadTestHandler : public TestHandler {
|
||||||
CefRegisterSchemeHandlerFactory("http", kTestDomain, scheme_factory);
|
CefRegisterSchemeHandlerFactory("http", kTestDomain, scheme_factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_mode_ != CLICKED_REJECTED) {
|
if (!is_clicked() || is_clicked_and_downloaded()) {
|
||||||
// Create a new temporary directory.
|
// Create a new temporary directory.
|
||||||
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||||
test_path_ =
|
test_path_ =
|
||||||
|
@ -226,19 +235,19 @@ class DownloadTestHandler : public TestHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_clicked()) {
|
if (is_clicked()) {
|
||||||
std::string url;
|
if (test_mode_ == CLICKED || test_mode_ == CLICKED_BLOCKED) {
|
||||||
if (test_mode_ == CLICKED) {
|
download_url_ = kTestDownloadUrl;
|
||||||
url = kTestDownloadUrl;
|
} else if (test_mode_ == CLICKED_INVALID) {
|
||||||
} else if (test_mode_ == CLICKED_REJECTED) {
|
download_url_ = "invalid:foo@example.com";
|
||||||
url = "invalid:foo@example.com";
|
|
||||||
} else {
|
} else {
|
||||||
EXPECT_TRUE(false); // Not reached.
|
EXPECT_TRUE(false); // Not reached.
|
||||||
}
|
}
|
||||||
AddResource(
|
AddResource(kTestStartUrl,
|
||||||
kTestStartUrl,
|
"<html><body><a href=\"" + download_url_ +
|
||||||
"<html><body><a href=\"" + url + "\">CLICK ME</a></body></html>",
|
"\">CLICK ME</a></body></html>",
|
||||||
"text/html");
|
"text/html");
|
||||||
} else {
|
} else {
|
||||||
|
download_url_ = kTestStartUrl;
|
||||||
AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
|
AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
|
||||||
"text/html");
|
"text/html");
|
||||||
}
|
}
|
||||||
|
@ -264,9 +273,9 @@ class DownloadTestHandler : public TestHandler {
|
||||||
// Begin the download by clicking a link.
|
// Begin the download by clicking a link.
|
||||||
// ALT key will trigger download of custom protocol links.
|
// ALT key will trigger download of custom protocol links.
|
||||||
SendClick(browser,
|
SendClick(browser,
|
||||||
test_mode_ == CLICKED_REJECTED ? EVENTFLAG_ALT_DOWN : 0);
|
test_mode_ == CLICKED_INVALID ? EVENTFLAG_ALT_DOWN : 0);
|
||||||
|
|
||||||
if (test_mode_ == CLICKED_REJECTED) {
|
if (is_clicked() && !is_clicked_and_downloaded()) {
|
||||||
// Destroy the test after a bit because there will be no further
|
// Destroy the test after a bit because there will be no further
|
||||||
// callbacks.
|
// callbacks.
|
||||||
CefPostDelayedTask(
|
CefPostDelayedTask(
|
||||||
|
@ -316,6 +325,23 @@ class DownloadTestHandler : public TestHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& url,
|
||||||
|
const CefString& request_method) override {
|
||||||
|
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||||
|
EXPECT_FALSE(got_can_download_);
|
||||||
|
EXPECT_FALSE(got_on_before_download_);
|
||||||
|
EXPECT_TRUE(is_clicked());
|
||||||
|
|
||||||
|
got_can_download_.yes();
|
||||||
|
|
||||||
|
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||||
|
EXPECT_STREQ(download_url_.c_str(), url.ToString().c_str());
|
||||||
|
EXPECT_STREQ("GET", request_method.ToString().c_str());
|
||||||
|
|
||||||
|
return test_mode_ != CLICKED_BLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
void OnBeforeDownload(
|
void OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
|
@ -324,6 +350,12 @@ class DownloadTestHandler : public TestHandler {
|
||||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||||
EXPECT_FALSE(got_on_before_download_);
|
EXPECT_FALSE(got_on_before_download_);
|
||||||
|
|
||||||
|
if (is_clicked()) {
|
||||||
|
EXPECT_TRUE(got_can_download_);
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(got_can_download_);
|
||||||
|
}
|
||||||
|
|
||||||
got_on_before_download_.yes();
|
got_on_before_download_.yes();
|
||||||
|
|
||||||
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||||
|
@ -460,12 +492,24 @@ class DownloadTestHandler : public TestHandler {
|
||||||
CefRegisterSchemeHandlerFactory("http", kTestDomain, nullptr);
|
CefRegisterSchemeHandlerFactory("http", kTestDomain, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_mode_ == CLICKED_REJECTED) {
|
if (is_clicked()) {
|
||||||
|
EXPECT_TRUE(got_can_download_);
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(got_can_download_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_mode_ == CLICKED_INVALID) {
|
||||||
|
// The invalid protocol request is not handled.
|
||||||
EXPECT_FALSE(got_download_request_);
|
EXPECT_FALSE(got_download_request_);
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(got_download_request_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_clicked() && !is_clicked_and_downloaded()) {
|
||||||
|
// The download never proceeds.
|
||||||
EXPECT_FALSE(got_on_before_download_);
|
EXPECT_FALSE(got_on_before_download_);
|
||||||
EXPECT_FALSE(got_on_download_updated_);
|
EXPECT_FALSE(got_on_download_updated_);
|
||||||
} else {
|
} else {
|
||||||
EXPECT_TRUE(got_download_request_);
|
|
||||||
EXPECT_TRUE(got_on_before_download_);
|
EXPECT_TRUE(got_on_before_download_);
|
||||||
EXPECT_TRUE(got_on_download_updated_);
|
EXPECT_TRUE(got_on_download_updated_);
|
||||||
}
|
}
|
||||||
|
@ -475,7 +519,8 @@ class DownloadTestHandler : public TestHandler {
|
||||||
else
|
else
|
||||||
EXPECT_FALSE(got_nav_load_);
|
EXPECT_FALSE(got_nav_load_);
|
||||||
|
|
||||||
if (test_mode_ == PENDING || test_mode_ == CLICKED_REJECTED) {
|
if (!is_downloaded()) {
|
||||||
|
// The download never completes.
|
||||||
EXPECT_FALSE(got_download_complete_);
|
EXPECT_FALSE(got_download_complete_);
|
||||||
EXPECT_FALSE(got_full_path_);
|
EXPECT_FALSE(got_full_path_);
|
||||||
} else {
|
} else {
|
||||||
|
@ -519,6 +564,7 @@ class DownloadTestHandler : public TestHandler {
|
||||||
// Used with PENDING test mode.
|
// Used with PENDING test mode.
|
||||||
CefRefPtr<CefDownloadItemCallback> download_item_callback_;
|
CefRefPtr<CefDownloadItemCallback> download_item_callback_;
|
||||||
|
|
||||||
|
std::string download_url_;
|
||||||
CefScopedTempDir temp_dir_;
|
CefScopedTempDir temp_dir_;
|
||||||
std::string test_path_;
|
std::string test_path_;
|
||||||
uint32 download_id_;
|
uint32 download_id_;
|
||||||
|
@ -526,6 +572,7 @@ class DownloadTestHandler : public TestHandler {
|
||||||
bool destroyed_ = false;
|
bool destroyed_ = false;
|
||||||
|
|
||||||
TrackCallback got_download_request_;
|
TrackCallback got_download_request_;
|
||||||
|
TrackCallback got_can_download_;
|
||||||
TrackCallback got_on_before_download_;
|
TrackCallback got_on_before_download_;
|
||||||
TrackCallback got_on_download_updated_;
|
TrackCallback got_on_download_updated_;
|
||||||
TrackCallback got_full_path_;
|
TrackCallback got_full_path_;
|
||||||
|
@ -542,14 +589,18 @@ class DownloadTestHandler : public TestHandler {
|
||||||
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
||||||
|
|
||||||
// Test a programmatic download.
|
// Test a programmatic download.
|
||||||
DOWNLOAD_TEST_GROUP(Programmatic, PROGAMMATIC)
|
DOWNLOAD_TEST_GROUP(Programmatic, PROGRAMMATIC)
|
||||||
|
|
||||||
// Test a clicked download.
|
// Test a clicked download.
|
||||||
DOWNLOAD_TEST_GROUP(Clicked, CLICKED)
|
DOWNLOAD_TEST_GROUP(Clicked, CLICKED)
|
||||||
|
|
||||||
// Test a clicked download where the protocol is invalid and therefore rejected.
|
// Test a clicked download where the protocol is invalid and therefore rejected.
|
||||||
// There will be no resulting CefDownloadHandler callbacks.
|
// There will be no resulting CefDownloadHandler callbacks.
|
||||||
DOWNLOAD_TEST_GROUP(ClickedRejected, CLICKED_REJECTED)
|
DOWNLOAD_TEST_GROUP(ClickedInvalid, CLICKED_INVALID)
|
||||||
|
|
||||||
|
// Test a clicked download where CanDownload returns false.
|
||||||
|
// There will be no resulting CefDownloadHandler callbacks.
|
||||||
|
DOWNLOAD_TEST_GROUP(ClickedBlocked, CLICKED_BLOCKED)
|
||||||
|
|
||||||
// Test where the download completes after cross-origin navigation.
|
// Test where the download completes after cross-origin navigation.
|
||||||
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED)
|
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED)
|
||||||
|
|
Loading…
Reference in New Issue