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
|
||||
// more information.
|
||||
//
|
||||
// $hash=ec13ec3e2819e4ac49792c3a1c57bc60b45fb95b$
|
||||
// $hash=33862915eb4156a70794a346a090154c468763e2$
|
||||
//
|
||||
|
||||
#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;
|
||||
|
||||
///
|
||||
// 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
|
||||
// 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
|
||||
// hash value will change if any platform is affected whereas the platform hash
|
||||
// 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)
|
||||
#define CEF_API_HASH_PLATFORM "0887a2a4ef42c8e2e33aba6662d2891f020e810a"
|
||||
#define CEF_API_HASH_PLATFORM "e08d5cc79cedebc94efc39536c27b6c30d24c9df"
|
||||
#elif defined(OS_MAC)
|
||||
#define CEF_API_HASH_PLATFORM "3d220485ac3df3a74e15db819ea16c98f78116ae"
|
||||
#define CEF_API_HASH_PLATFORM "86626c6c27b29841a4bf01c145e2d7990a73abf0"
|
||||
#elif defined(OS_LINUX)
|
||||
#define CEF_API_HASH_PLATFORM "ee08ceb06c69dac1ac16361daabe3378c9d2d621"
|
||||
#define CEF_API_HASH_PLATFORM "a19b7983d07d0e6afe0ae46c1768111078995c5e"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -90,6 +90,20 @@ class CefDownloadItemCallback : public virtual CefBaseRefCounted {
|
|||
/*--cef(source=client)--*/
|
||||
class CefDownloadHandler : public virtual CefBaseRefCounted {
|
||||
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
|
||||
// the download file. By default the download will be canceled. Execute
|
||||
|
|
|
@ -1225,6 +1225,13 @@ bool AlloyBrowserHostImpl::HandleContextMenu(
|
|||
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(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
|
|
|
@ -225,6 +225,9 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||
bool TakeFocus(content::WebContents* source, bool reverse) override;
|
||||
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
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::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
|
|
|
@ -180,6 +180,23 @@ void CefBrowserContentsDelegate::ExitFullscreenModeForTab(
|
|||
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
|
||||
CefBrowserContentsDelegate::PreHandleKeyboardEvent(
|
||||
content::WebContents* source,
|
||||
|
|
|
@ -101,6 +101,9 @@ class CefBrowserContentsDelegate : public content::WebContentsDelegate,
|
|||
content::RenderFrameHost* requesting_frame,
|
||||
const blink::mojom::FullscreenOptions& options) 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::WebContents* source,
|
||||
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(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
|
|
|
@ -86,6 +86,9 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
|
|||
content::RenderFrameHost* requesting_frame,
|
||||
const blink::mojom::FullscreenOptions& options) 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::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=496b226297ba7d5fa5e7e7bd4117c417e26fae59$
|
||||
// $hash=89f651178065dbc03e70e763085bf9125dda6640$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
|
||||
|
@ -23,6 +23,40 @@ namespace {
|
|||
|
||||
// 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
|
||||
download_handler_on_before_download(struct _cef_download_handler_t* self,
|
||||
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.
|
||||
|
||||
CefDownloadHandlerCppToC::CefDownloadHandlerCppToC() {
|
||||
GetStruct()->can_download = download_handler_can_download;
|
||||
GetStruct()->on_before_download = download_handler_on_before_download;
|
||||
GetStruct()->on_download_updated = download_handler_on_download_updated;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=c4e47ffd023b528b9c5b658126f4a1d9fd05cf98$
|
||||
// $hash=bb3a8a9a02dc3d2e4bdf0e926f61adc05e3af351$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
|
||||
|
@ -21,6 +21,40 @@
|
|||
|
||||
// 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")
|
||||
void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=172a12dd9e68b65afff9eef5b93f0e480beaf904$
|
||||
// $hash=fa32af3253cface693ec3ef420863852f5c68379$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
|
||||
|
@ -35,6 +35,9 @@ class CefDownloadHandlerCToCpp
|
|||
virtual ~CefDownloadHandlerCToCpp();
|
||||
|
||||
// CefDownloadHandler methods.
|
||||
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
const CefString& request_method) override;
|
||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
|
|
|
@ -13,7 +13,7 @@ index 9e534ff1683f1..de406f5879be0 100644
|
|||
return false;
|
||||
}
|
||||
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
|
||||
@@ -262,6 +262,25 @@
|
||||
|
@ -159,7 +159,27 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
void Browser::ContentsMouseEvent(WebContents* source,
|
||||
bool motion,
|
||||
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.
|
||||
task_manager::WebContentsTags::CreateForTabContents(new_contents);
|
||||
|
@ -170,7 +190,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
}
|
||||
|
||||
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) {
|
||||
if (web_contents == tab_strip_model_->GetActiveWebContents())
|
||||
UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE);
|
||||
|
@ -179,7 +199,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
}
|
||||
|
||||
content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
|
||||
@@ -1906,11 +1988,15 @@ void Browser::EnterFullscreenModeForTab(
|
||||
@@ -1906,11 +2001,15 @@ void Browser::EnterFullscreenModeForTab(
|
||||
const blink::mojom::FullscreenOptions& options) {
|
||||
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
|
||||
requesting_frame, options.display_id);
|
||||
|
@ -195,7 +215,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
}
|
||||
|
||||
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):
|
||||
|
||||
StatusBubble* Browser::GetStatusBubble() {
|
||||
|
@ -217,7 +237,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
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);
|
||||
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
|
||||
}
|
||||
|
@ -227,7 +247,7 @@ index 04e327d970b87..6bd83131116d9 100644
|
|||
|
||||
void Browser::TabDetachedAtImpl(content::WebContents* contents,
|
||||
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
|
||||
@@ -21,6 +21,7 @@
|
||||
|
@ -288,7 +308,7 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
|||
// Get the FindBarController for this browser, creating it if it does not
|
||||
// yet exist.
|
||||
FindBarController* GetFindBarController();
|
||||
@@ -794,6 +817,11 @@ class Browser : public TabStripModelObserver,
|
||||
@@ -794,11 +817,19 @@ class Browser : public TabStripModelObserver,
|
||||
void SetContentsBounds(content::WebContents* source,
|
||||
const gfx::Rect& bounds) override;
|
||||
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
||||
|
@ -300,7 +320,15 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
|||
void ContentsMouseEvent(content::WebContents* source,
|
||||
bool motion,
|
||||
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_;
|
||||
bool initial_visible_on_all_workspaces_state_;
|
||||
|
||||
|
@ -309,7 +337,7 @@ index a63ba24be314e..38a6dcbf034ef 100644
|
|||
CreationSource creation_source_ = CreationSource::kUnknown;
|
||||
|
||||
UnloadController unload_controller_;
|
||||
@@ -1257,6 +1287,10 @@ class Browser : public TabStripModelObserver,
|
||||
@@ -1257,6 +1290,10 @@ class Browser : public TabStripModelObserver,
|
||||
extension_browser_window_helper_;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -515,6 +515,21 @@ bool ClientHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
|
|||
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(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
|
|
|
@ -170,6 +170,9 @@ class ClientHandler : public CefClient,
|
|||
const CefCursorInfo& custom_cursor_info) override;
|
||||
|
||||
// CefDownloadHandler methods
|
||||
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
const CefString& request_method) override;
|
||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
|
|
|
@ -169,11 +169,12 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
|||
class DownloadTestHandler : public TestHandler {
|
||||
public:
|
||||
enum TestMode {
|
||||
PROGAMMATIC,
|
||||
PROGRAMMATIC,
|
||||
NAVIGATED,
|
||||
PENDING,
|
||||
CLICKED,
|
||||
CLICKED_REJECTED,
|
||||
CLICKED_INVALID,
|
||||
CLICKED_BLOCKED,
|
||||
};
|
||||
|
||||
DownloadTestHandler(TestMode test_mode,
|
||||
|
@ -186,7 +187,15 @@ class DownloadTestHandler : public TestHandler {
|
|||
verified_results_(false) {}
|
||||
|
||||
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 {
|
||||
|
@ -212,7 +221,7 @@ class DownloadTestHandler : public TestHandler {
|
|||
CefRegisterSchemeHandlerFactory("http", kTestDomain, scheme_factory);
|
||||
}
|
||||
|
||||
if (test_mode_ != CLICKED_REJECTED) {
|
||||
if (!is_clicked() || is_clicked_and_downloaded()) {
|
||||
// Create a new temporary directory.
|
||||
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||
test_path_ =
|
||||
|
@ -226,19 +235,19 @@ class DownloadTestHandler : public TestHandler {
|
|||
}
|
||||
|
||||
if (is_clicked()) {
|
||||
std::string url;
|
||||
if (test_mode_ == CLICKED) {
|
||||
url = kTestDownloadUrl;
|
||||
} else if (test_mode_ == CLICKED_REJECTED) {
|
||||
url = "invalid:foo@example.com";
|
||||
if (test_mode_ == CLICKED || test_mode_ == CLICKED_BLOCKED) {
|
||||
download_url_ = kTestDownloadUrl;
|
||||
} else if (test_mode_ == CLICKED_INVALID) {
|
||||
download_url_ = "invalid:foo@example.com";
|
||||
} else {
|
||||
EXPECT_TRUE(false); // Not reached.
|
||||
}
|
||||
AddResource(
|
||||
kTestStartUrl,
|
||||
"<html><body><a href=\"" + url + "\">CLICK ME</a></body></html>",
|
||||
"text/html");
|
||||
AddResource(kTestStartUrl,
|
||||
"<html><body><a href=\"" + download_url_ +
|
||||
"\">CLICK ME</a></body></html>",
|
||||
"text/html");
|
||||
} else {
|
||||
download_url_ = kTestStartUrl;
|
||||
AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
|
||||
"text/html");
|
||||
}
|
||||
|
@ -264,9 +273,9 @@ class DownloadTestHandler : public TestHandler {
|
|||
// Begin the download by clicking a link.
|
||||
// ALT key will trigger download of custom protocol links.
|
||||
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
|
||||
// callbacks.
|
||||
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(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
|
@ -324,6 +350,12 @@ class DownloadTestHandler : public TestHandler {
|
|||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
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();
|
||||
|
||||
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||
|
@ -460,12 +492,24 @@ class DownloadTestHandler : public TestHandler {
|
|||
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_);
|
||||
} 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_download_updated_);
|
||||
} else {
|
||||
EXPECT_TRUE(got_download_request_);
|
||||
EXPECT_TRUE(got_on_before_download_);
|
||||
EXPECT_TRUE(got_on_download_updated_);
|
||||
}
|
||||
|
@ -475,7 +519,8 @@ class DownloadTestHandler : public TestHandler {
|
|||
else
|
||||
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_full_path_);
|
||||
} else {
|
||||
|
@ -519,6 +564,7 @@ class DownloadTestHandler : public TestHandler {
|
|||
// Used with PENDING test mode.
|
||||
CefRefPtr<CefDownloadItemCallback> download_item_callback_;
|
||||
|
||||
std::string download_url_;
|
||||
CefScopedTempDir temp_dir_;
|
||||
std::string test_path_;
|
||||
uint32 download_id_;
|
||||
|
@ -526,6 +572,7 @@ class DownloadTestHandler : public TestHandler {
|
|||
bool destroyed_ = false;
|
||||
|
||||
TrackCallback got_download_request_;
|
||||
TrackCallback got_can_download_;
|
||||
TrackCallback got_on_before_download_;
|
||||
TrackCallback got_on_download_updated_;
|
||||
TrackCallback got_full_path_;
|
||||
|
@ -542,14 +589,18 @@ class DownloadTestHandler : public TestHandler {
|
|||
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
||||
|
||||
// Test a programmatic download.
|
||||
DOWNLOAD_TEST_GROUP(Programmatic, PROGAMMATIC)
|
||||
DOWNLOAD_TEST_GROUP(Programmatic, PROGRAMMATIC)
|
||||
|
||||
// Test a clicked download.
|
||||
DOWNLOAD_TEST_GROUP(Clicked, CLICKED)
|
||||
|
||||
// Test a clicked download where the protocol is invalid and therefore rejected.
|
||||
// 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.
|
||||
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED)
|
||||
|
|
Loading…
Reference in New Issue