mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
chrome: Add CefDownloadHandler support (see #3681)
Behaves the same as Alloy runtime except that CanDownload is not called for invalid protocol schemes.
This commit is contained in:
4
BUILD.gn
4
BUILD.gn
@ -465,6 +465,8 @@ source_set("libcef_static") {
|
|||||||
"libcef/browser/alloy/alloy_browser_main.h",
|
"libcef/browser/alloy/alloy_browser_main.h",
|
||||||
"libcef/browser/alloy/alloy_content_browser_client.cc",
|
"libcef/browser/alloy/alloy_content_browser_client.cc",
|
||||||
"libcef/browser/alloy/alloy_content_browser_client.h",
|
"libcef/browser/alloy/alloy_content_browser_client.h",
|
||||||
|
"libcef/browser/alloy/alloy_download_manager_delegate.cc",
|
||||||
|
"libcef/browser/alloy/alloy_download_manager_delegate.h",
|
||||||
"libcef/browser/alloy/alloy_download_util.cc",
|
"libcef/browser/alloy/alloy_download_util.cc",
|
||||||
"libcef/browser/alloy/alloy_download_util.h",
|
"libcef/browser/alloy/alloy_download_util.h",
|
||||||
"libcef/browser/alloy/alloy_web_contents_view_delegate.cc",
|
"libcef/browser/alloy/alloy_web_contents_view_delegate.cc",
|
||||||
@ -576,6 +578,8 @@ source_set("libcef_static") {
|
|||||||
"libcef/browser/download_item_impl.h",
|
"libcef/browser/download_item_impl.h",
|
||||||
"libcef/browser/download_manager_delegate.cc",
|
"libcef/browser/download_manager_delegate.cc",
|
||||||
"libcef/browser/download_manager_delegate.h",
|
"libcef/browser/download_manager_delegate.h",
|
||||||
|
"libcef/browser/download_manager_delegate_impl.cc",
|
||||||
|
"libcef/browser/download_manager_delegate_impl.h",
|
||||||
"libcef/browser/extension_impl.cc",
|
"libcef/browser/extension_impl.cc",
|
||||||
"libcef/browser/extension_impl.h",
|
"libcef/browser/extension_impl.h",
|
||||||
"libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc",
|
"libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc",
|
||||||
|
@ -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=60a08a60be70e8fe5df17f18f8e5758e1830d5e1$
|
// $hash=7ecfb07a95315ff81937e9f68d419122fc88f1b7$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_
|
#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_
|
||||||
@ -117,12 +117,13 @@ typedef struct _cef_download_handler_t {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// Called before a download begins. |suggested_name| is the suggested name
|
/// Called before a download begins. |suggested_name| is the suggested name
|
||||||
/// for the download file. By default the download will be canceled. Execute
|
/// for the download file. Return true (1) and execute |callback| either
|
||||||
/// |callback| either asynchronously or in this function to continue the
|
/// asynchronously or in this function to continue or cancel the download.
|
||||||
/// download if desired. Do not keep a reference to |download_item| outside of
|
/// Return false (0) to proceed with default handling (cancel with Alloy
|
||||||
/// this function.
|
/// style, download shelf with Chrome style). Do not keep a reference to
|
||||||
|
/// |download_item| outside of this function.
|
||||||
///
|
///
|
||||||
void(CEF_CALLBACK* on_before_download)(
|
int(CEF_CALLBACK* on_before_download)(
|
||||||
struct _cef_download_handler_t* self,
|
struct _cef_download_handler_t* self,
|
||||||
struct _cef_browser_t* browser,
|
struct _cef_browser_t* browser,
|
||||||
struct _cef_download_item_t* download_item,
|
struct _cef_download_item_t* download_item,
|
||||||
|
@ -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 "faa8a52df058a26e1228da66052a9900a7120de4"
|
#define CEF_API_HASH_UNIVERSAL "73e8743408bfeba0df3b567bfd04b2eb642df11d"
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#define CEF_API_HASH_PLATFORM "41a15a683e4a2b927f043c22d8a9f07671168170"
|
#define CEF_API_HASH_PLATFORM "3a73f4c69062c6f413e00c1821f6e6df91a2a787"
|
||||||
#elif defined(OS_MAC)
|
#elif defined(OS_MAC)
|
||||||
#define CEF_API_HASH_PLATFORM "6933ff4566b919c045ff0743682889d45ffcba28"
|
#define CEF_API_HASH_PLATFORM "f5fb92747082f06a9c42724b0b717accc29e3879"
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
#define CEF_API_HASH_PLATFORM "b12778ab8fd0974e45a246484a31d12f097c7936"
|
#define CEF_API_HASH_PLATFORM "8775d620c6b17725bddba2c1c3a21353b4d8acb1"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -106,17 +106,19 @@ class CefDownloadHandler : public virtual CefBaseRefCounted {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// Called before a download begins. |suggested_name| is the suggested name
|
/// Called before a download begins. |suggested_name| is the suggested name
|
||||||
/// for the download file. By default the download will be canceled. Execute
|
/// for the download file. Return true and execute |callback| either
|
||||||
/// |callback| either asynchronously or in this method to continue the
|
/// asynchronously or in this method to continue or cancel the download.
|
||||||
/// download if desired. Do not keep a reference to |download_item| outside of
|
/// Return false to proceed with default handling (cancel with Alloy style,
|
||||||
/// this method.
|
/// download shelf with Chrome style). Do not keep a reference to
|
||||||
|
/// |download_item| outside of this method.
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual void OnBeforeDownload(
|
virtual bool OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
CefRefPtr<CefBeforeDownloadCallback> callback) = 0;
|
CefRefPtr<CefBeforeDownloadCallback> callback) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Called when a download's status or progress information has been updated.
|
/// Called when a download's status or progress information has been updated.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "libcef/browser/download_manager_delegate.h"
|
#include "libcef/browser/alloy/alloy_download_manager_delegate.h"
|
||||||
#include "libcef/browser/extensions/extension_system.h"
|
#include "libcef/browser/extensions/extension_system.h"
|
||||||
#include "libcef/browser/prefs/browser_prefs.h"
|
#include "libcef/browser/prefs/browser_prefs.h"
|
||||||
#include "libcef/browser/ssl_host_state_delegate.h"
|
#include "libcef/browser/ssl_host_state_delegate.h"
|
||||||
@ -336,7 +336,7 @@ content::DownloadManagerDelegate*
|
|||||||
AlloyBrowserContext::GetDownloadManagerDelegate() {
|
AlloyBrowserContext::GetDownloadManagerDelegate() {
|
||||||
if (!download_manager_delegate_) {
|
if (!download_manager_delegate_) {
|
||||||
download_manager_delegate_ =
|
download_manager_delegate_ =
|
||||||
std::make_unique<CefDownloadManagerDelegate>(GetDownloadManager());
|
std::make_unique<AlloyDownloadManagerDelegate>(GetDownloadManager());
|
||||||
}
|
}
|
||||||
return download_manager_delegate_.get();
|
return download_manager_delegate_.get();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "components/proxy_config/pref_proxy_config_tracker.h"
|
#include "components/proxy_config/pref_proxy_config_tracker.h"
|
||||||
#include "components/visitedlink/browser/visitedlink_delegate.h"
|
#include "components/visitedlink/browser/visitedlink_delegate.h"
|
||||||
|
|
||||||
class CefDownloadManagerDelegate;
|
class AlloyDownloadManagerDelegate;
|
||||||
class CefSSLHostStateDelegate;
|
class CefSSLHostStateDelegate;
|
||||||
class CefVisitedLinkListener;
|
class CefVisitedLinkListener;
|
||||||
class PrefService;
|
class PrefService;
|
||||||
@ -128,7 +128,7 @@ class AlloyBrowserContext : public ChromeProfileAlloy,
|
|||||||
std::unique_ptr<PrefService> pref_service_;
|
std::unique_ptr<PrefService> pref_service_;
|
||||||
std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
|
std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
|
||||||
|
|
||||||
std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_;
|
std::unique_ptr<AlloyDownloadManagerDelegate> download_manager_delegate_;
|
||||||
std::unique_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
|
std::unique_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
|
||||||
std::unique_ptr<visitedlink::VisitedLinkWriter> visitedlink_master_;
|
std::unique_ptr<visitedlink::VisitedLinkWriter> visitedlink_master_;
|
||||||
// |visitedlink_listener_| is owned by visitedlink_master_.
|
// |visitedlink_listener_| is owned by visitedlink_master_.
|
||||||
|
22
libcef/browser/alloy/alloy_download_manager_delegate.cc
Normal file
22
libcef/browser/alloy/alloy_download_manager_delegate.cc
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "libcef/browser/alloy/alloy_download_manager_delegate.h"
|
||||||
|
|
||||||
|
#include "chrome/common/chrome_constants.h"
|
||||||
|
#include "components/download/public/common/download_item.h"
|
||||||
|
|
||||||
|
AlloyDownloadManagerDelegate::AlloyDownloadManagerDelegate(
|
||||||
|
content::DownloadManager* manager)
|
||||||
|
: CefDownloadManagerDelegateImpl(manager, /*alloy_bootstrap=*/true) {}
|
||||||
|
|
||||||
|
void AlloyDownloadManagerDelegate::GetNextId(
|
||||||
|
content::DownloadIdCallback callback) {
|
||||||
|
static uint32_t next_id = download::DownloadItem::kInvalidId + 1;
|
||||||
|
std::move(callback).Run(next_id++);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AlloyDownloadManagerDelegate::ApplicationClientIdForFileScanning() {
|
||||||
|
return std::string(chrome::kApplicationClientIDStringForAVScanning);
|
||||||
|
}
|
26
libcef/browser/alloy/alloy_download_manager_delegate.h
Normal file
26
libcef/browser/alloy/alloy_download_manager_delegate.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_MANAGER_DELEGATE_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_MANAGER_DELEGATE_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/download_manager_delegate_impl.h"
|
||||||
|
|
||||||
|
// Specialization for the Alloy bootstrap.
|
||||||
|
class AlloyDownloadManagerDelegate : public CefDownloadManagerDelegateImpl {
|
||||||
|
public:
|
||||||
|
explicit AlloyDownloadManagerDelegate(content::DownloadManager* manager);
|
||||||
|
|
||||||
|
AlloyDownloadManagerDelegate(const AlloyDownloadManagerDelegate&) = delete;
|
||||||
|
AlloyDownloadManagerDelegate& operator=(const AlloyDownloadManagerDelegate&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// DownloadManagerDelegate methods.
|
||||||
|
void GetNextId(content::DownloadIdCallback callback) override;
|
||||||
|
std::string ApplicationClientIdForFileScanning() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_MANAGER_DELEGATE_H_
|
@ -1,479 +1,20 @@
|
|||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
// Copyright 2024 The Chromium Embedded Framework Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
// found in the LICENSE file.
|
// in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/download_manager_delegate.h"
|
#include "libcef/browser/download_manager_delegate.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include "libcef/browser/download_manager_delegate_impl.h"
|
||||||
|
#include "libcef/features/runtime_checks.h"
|
||||||
|
|
||||||
#include "include/cef_download_handler.h"
|
namespace cef {
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
|
||||||
#include "libcef/browser/context.h"
|
|
||||||
#include "libcef/browser/download_item_impl.h"
|
|
||||||
#include "libcef/browser/thread_util.h"
|
|
||||||
|
|
||||||
#include "base/files/file_util.h"
|
// static
|
||||||
#include "base/functional/bind.h"
|
std::unique_ptr<cef::DownloadManagerDelegate> DownloadManagerDelegate::Create(
|
||||||
#include "base/logging.h"
|
content::DownloadManager* download_manager) {
|
||||||
#include "base/path_service.h"
|
REQUIRE_CHROME_RUNTIME();
|
||||||
#include "base/strings/string_util.h"
|
return std::make_unique<CefDownloadManagerDelegateImpl>(
|
||||||
#include "base/strings/utf_string_conversions.h"
|
download_manager, /*alloy_bootstrap=*/false);
|
||||||
#include "chrome/common/chrome_constants.h"
|
|
||||||
#include "content/public/browser/browser_context.h"
|
|
||||||
#include "content/public/browser/download_item_utils.h"
|
|
||||||
#include "content/public/browser/web_contents.h"
|
|
||||||
#include "net/base/filename_util.h"
|
|
||||||
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
|
||||||
|
|
||||||
using content::DownloadManager;
|
|
||||||
using content::WebContents;
|
|
||||||
using download::DownloadItem;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Helper function to retrieve the CefDownloadHandler.
|
|
||||||
CefRefPtr<CefDownloadHandler> GetDownloadHandler(
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser) {
|
|
||||||
CefRefPtr<CefClient> client = browser->GetClient();
|
|
||||||
if (client.get()) {
|
|
||||||
return client->GetDownloadHandler();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunDownloadTargetCallback(download::DownloadTargetCallback callback,
|
} // namespace cef
|
||||||
const base::FilePath& path) {
|
|
||||||
download::DownloadTargetInfo target_info;
|
|
||||||
target_info.target_path = path;
|
|
||||||
target_info.intermediate_path = path;
|
|
||||||
std::move(callback).Run(std::move(target_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
// CefBeforeDownloadCallback implementation.
|
|
||||||
class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|
||||||
public:
|
|
||||||
CefBeforeDownloadCallbackImpl(const base::WeakPtr<DownloadManager>& manager,
|
|
||||||
uint32_t download_id,
|
|
||||||
const base::FilePath& suggested_name,
|
|
||||||
download::DownloadTargetCallback callback)
|
|
||||||
: manager_(manager),
|
|
||||||
download_id_(download_id),
|
|
||||||
suggested_name_(suggested_name),
|
|
||||||
callback_(std::move(callback)) {}
|
|
||||||
|
|
||||||
CefBeforeDownloadCallbackImpl(const CefBeforeDownloadCallbackImpl&) = delete;
|
|
||||||
CefBeforeDownloadCallbackImpl& operator=(
|
|
||||||
const CefBeforeDownloadCallbackImpl&) = delete;
|
|
||||||
|
|
||||||
void Continue(const CefString& download_path, bool show_dialog) override {
|
|
||||||
if (CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
if (download_id_ <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager_) {
|
|
||||||
base::FilePath path = base::FilePath(download_path);
|
|
||||||
CEF_POST_USER_VISIBLE_TASK(
|
|
||||||
base::BindOnce(&CefBeforeDownloadCallbackImpl::GenerateFilename,
|
|
||||||
manager_, download_id_, suggested_name_, path,
|
|
||||||
show_dialog, std::move(callback_)));
|
|
||||||
}
|
|
||||||
|
|
||||||
download_id_ = 0;
|
|
||||||
} else {
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::BindOnce(&CefBeforeDownloadCallbackImpl::Continue,
|
|
||||||
this, download_path, show_dialog));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void GenerateFilename(base::WeakPtr<DownloadManager> manager,
|
|
||||||
uint32_t download_id,
|
|
||||||
const base::FilePath& suggested_name,
|
|
||||||
const base::FilePath& download_path,
|
|
||||||
bool show_dialog,
|
|
||||||
download::DownloadTargetCallback callback) {
|
|
||||||
CEF_REQUIRE_BLOCKING();
|
|
||||||
|
|
||||||
base::FilePath suggested_path = download_path;
|
|
||||||
if (!suggested_path.empty()) {
|
|
||||||
// Create the directory if necessary.
|
|
||||||
base::FilePath dir_path = suggested_path.DirName();
|
|
||||||
if (!base::DirectoryExists(dir_path) &&
|
|
||||||
!base::CreateDirectory(dir_path)) {
|
|
||||||
DCHECK(false) << "failed to create the download directory";
|
|
||||||
suggested_path.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (suggested_path.empty()) {
|
|
||||||
if (base::PathService::Get(base::DIR_TEMP, &suggested_path)) {
|
|
||||||
// Use the temp directory.
|
|
||||||
suggested_path = suggested_path.Append(suggested_name);
|
|
||||||
} else {
|
|
||||||
// Use the current working directory.
|
|
||||||
suggested_path = suggested_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CEF_POST_TASK(
|
|
||||||
CEF_UIT,
|
|
||||||
base::BindOnce(&CefBeforeDownloadCallbackImpl::ChooseDownloadPath,
|
|
||||||
manager, download_id, suggested_path, show_dialog,
|
|
||||||
std::move(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ChooseDownloadPath(base::WeakPtr<DownloadManager> manager,
|
|
||||||
uint32_t download_id,
|
|
||||||
const base::FilePath& suggested_path,
|
|
||||||
bool show_dialog,
|
|
||||||
download::DownloadTargetCallback callback) {
|
|
||||||
if (!manager) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadItem* item = manager->GetDownload(download_id);
|
|
||||||
if (!item || item->GetState() != DownloadItem::IN_PROGRESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
|
|
||||||
if (show_dialog) {
|
|
||||||
WebContents* web_contents =
|
|
||||||
content::DownloadItemUtils::GetWebContents(item);
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser =
|
|
||||||
AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
|
|
||||||
if (browser.get()) {
|
|
||||||
handled = true;
|
|
||||||
|
|
||||||
blink::mojom::FileChooserParams params;
|
|
||||||
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
|
||||||
if (!suggested_path.empty()) {
|
|
||||||
params.default_file_name = suggested_path;
|
|
||||||
if (!suggested_path.Extension().empty()) {
|
|
||||||
params.accept_types.push_back(
|
|
||||||
CefString(suggested_path.Extension()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
browser->RunFileChooserForBrowser(
|
|
||||||
params,
|
|
||||||
base::BindOnce(
|
|
||||||
&CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
|
|
||||||
std::move(callback)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!handled) {
|
|
||||||
RunDownloadTargetCallback(std::move(callback), suggested_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ChooseDownloadPathCallback(
|
|
||||||
download::DownloadTargetCallback callback,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
|
||||||
DCHECK_LE(file_paths.size(), (size_t)1);
|
|
||||||
|
|
||||||
base::FilePath path;
|
|
||||||
if (file_paths.size() > 0) {
|
|
||||||
path = file_paths.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The download will be cancelled if |path| is empty.
|
|
||||||
RunDownloadTargetCallback(std::move(callback), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
base::WeakPtr<DownloadManager> manager_;
|
|
||||||
uint32_t download_id_;
|
|
||||||
base::FilePath suggested_name_;
|
|
||||||
download::DownloadTargetCallback callback_;
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(CefBeforeDownloadCallbackImpl);
|
|
||||||
};
|
|
||||||
|
|
||||||
// CefDownloadItemCallback implementation.
|
|
||||||
class CefDownloadItemCallbackImpl : public CefDownloadItemCallback {
|
|
||||||
public:
|
|
||||||
explicit CefDownloadItemCallbackImpl(
|
|
||||||
const base::WeakPtr<DownloadManager>& manager,
|
|
||||||
uint32_t download_id)
|
|
||||||
: manager_(manager), download_id_(download_id) {}
|
|
||||||
|
|
||||||
CefDownloadItemCallbackImpl(const CefDownloadItemCallbackImpl&) = delete;
|
|
||||||
CefDownloadItemCallbackImpl& operator=(const CefDownloadItemCallbackImpl&) =
|
|
||||||
delete;
|
|
||||||
|
|
||||||
void Cancel() override {
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::BindOnce(&CefDownloadItemCallbackImpl::DoCancel, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Pause() override {
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::BindOnce(&CefDownloadItemCallbackImpl::DoPause, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resume() override {
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::BindOnce(&CefDownloadItemCallbackImpl::DoResume, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void DoCancel() {
|
|
||||||
if (download_id_ <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager_) {
|
|
||||||
DownloadItem* item = manager_->GetDownload(download_id_);
|
|
||||||
if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
|
|
||||||
item->Cancel(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
download_id_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoPause() {
|
|
||||||
if (download_id_ <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager_) {
|
|
||||||
DownloadItem* item = manager_->GetDownload(download_id_);
|
|
||||||
if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
|
|
||||||
item->Pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoResume() {
|
|
||||||
if (download_id_ <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager_) {
|
|
||||||
DownloadItem* item = manager_->GetDownload(download_id_);
|
|
||||||
if (item && item->CanResume()) {
|
|
||||||
item->Resume(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base::WeakPtr<DownloadManager> manager_;
|
|
||||||
uint32_t download_id_;
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(CefDownloadItemCallbackImpl);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
CefDownloadManagerDelegate::CefDownloadManagerDelegate(DownloadManager* manager)
|
|
||||||
: manager_(manager), manager_ptr_factory_(manager) {
|
|
||||||
DCHECK(manager);
|
|
||||||
manager->AddObserver(this);
|
|
||||||
|
|
||||||
DownloadManager::DownloadVector items;
|
|
||||||
manager->GetAllDownloads(&items);
|
|
||||||
DownloadManager::DownloadVector::const_iterator it = items.begin();
|
|
||||||
for (; it != items.end(); ++it) {
|
|
||||||
OnDownloadCreated(manager, *it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CefDownloadManagerDelegate::~CefDownloadManagerDelegate() {
|
|
||||||
if (manager_) {
|
|
||||||
manager_->SetDelegate(nullptr);
|
|
||||||
manager_->RemoveObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!item_browser_map_.empty()) {
|
|
||||||
OnDownloadDestroyed(item_browser_map_.begin()->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::OnDownloadUpdated(DownloadItem* download) {
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser = GetBrowser(download);
|
|
||||||
CefRefPtr<CefDownloadHandler> handler;
|
|
||||||
if (browser.get()) {
|
|
||||||
handler = GetDownloadHandler(browser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler.get()) {
|
|
||||||
CefRefPtr<CefDownloadItemImpl> download_item(
|
|
||||||
new CefDownloadItemImpl(download));
|
|
||||||
CefRefPtr<CefDownloadItemCallback> callback(new CefDownloadItemCallbackImpl(
|
|
||||||
manager_ptr_factory_.GetWeakPtr(), download->GetId()));
|
|
||||||
|
|
||||||
handler->OnDownloadUpdated(browser.get(), download_item.get(), callback);
|
|
||||||
|
|
||||||
std::ignore = download_item->Detach(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::OnDownloadDestroyed(DownloadItem* item) {
|
|
||||||
item->RemoveObserver(this);
|
|
||||||
|
|
||||||
AlloyBrowserHostImpl* browser = nullptr;
|
|
||||||
|
|
||||||
ItemBrowserMap::iterator it = item_browser_map_.find(item);
|
|
||||||
DCHECK(it != item_browser_map_.end());
|
|
||||||
if (it != item_browser_map_.end()) {
|
|
||||||
browser = it->second;
|
|
||||||
item_browser_map_.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (browser) {
|
|
||||||
// Determine if any remaining DownloadItems are associated with the same
|
|
||||||
// browser. If not, then unregister as an observer.
|
|
||||||
bool has_remaining = false;
|
|
||||||
ItemBrowserMap::const_iterator it2 = item_browser_map_.begin();
|
|
||||||
for (; it2 != item_browser_map_.end(); ++it2) {
|
|
||||||
if (it2->second == browser) {
|
|
||||||
has_remaining = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_remaining) {
|
|
||||||
browser->RemoveObserver(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::OnDownloadCreated(DownloadManager* manager,
|
|
||||||
DownloadItem* item) {
|
|
||||||
// This callback may arrive after DetermineDownloadTarget, so we allow
|
|
||||||
// association from either method.
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser = GetOrAssociateBrowser(item);
|
|
||||||
if (!browser) {
|
|
||||||
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
|
||||||
// then an "interrupted" download will be started via DownloadManagerImpl::
|
|
||||||
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
|
||||||
// associated WebContents and consequently no associated CEF browser. In
|
|
||||||
// that case DetermineDownloadTarget will be called before this method.
|
|
||||||
// TODO(cef): Figure out how to expose this via a client callback.
|
|
||||||
const std::vector<GURL>& url_chain = item->GetUrlChain();
|
|
||||||
if (!url_chain.empty()) {
|
|
||||||
LOG(INFO) << "Rejected download of " << url_chain.back().spec();
|
|
||||||
}
|
|
||||||
item->Cancel(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::ManagerGoingDown(DownloadManager* manager) {
|
|
||||||
DCHECK_EQ(manager, manager_);
|
|
||||||
manager->SetDelegate(nullptr);
|
|
||||||
manager->RemoveObserver(this);
|
|
||||||
manager_ptr_factory_.InvalidateWeakPtrs();
|
|
||||||
manager_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefDownloadManagerDelegate::DetermineDownloadTarget(
|
|
||||||
DownloadItem* item,
|
|
||||||
download::DownloadTargetCallback* callback) {
|
|
||||||
const auto& forced_path = item->GetForcedFilePath();
|
|
||||||
if (!forced_path.empty()) {
|
|
||||||
RunDownloadTargetCallback(std::move(*callback), forced_path);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This callback may arrive before OnDownloadCreated, so we allow association
|
|
||||||
// from either method.
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser = GetOrAssociateBrowser(item);
|
|
||||||
CefRefPtr<CefDownloadHandler> handler;
|
|
||||||
if (browser.get()) {
|
|
||||||
handler = GetDownloadHandler(browser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler.get()) {
|
|
||||||
base::FilePath suggested_name = net::GenerateFileName(
|
|
||||||
item->GetURL(), item->GetContentDisposition(), std::string(),
|
|
||||||
item->GetSuggestedFilename(), item->GetMimeType(), "download");
|
|
||||||
|
|
||||||
CefRefPtr<CefDownloadItemImpl> download_item(new CefDownloadItemImpl(item));
|
|
||||||
CefRefPtr<CefBeforeDownloadCallback> callbackObj(
|
|
||||||
new CefBeforeDownloadCallbackImpl(manager_ptr_factory_.GetWeakPtr(),
|
|
||||||
item->GetId(), suggested_name,
|
|
||||||
std::move(*callback)));
|
|
||||||
|
|
||||||
handler->OnBeforeDownload(browser.get(), download_item.get(),
|
|
||||||
suggested_name.value(), callbackObj);
|
|
||||||
|
|
||||||
std::ignore = download_item->Detach(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::GetNextId(
|
|
||||||
content::DownloadIdCallback callback) {
|
|
||||||
static uint32_t next_id = DownloadItem::kInvalidId + 1;
|
|
||||||
std::move(callback).Run(next_id++);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CefDownloadManagerDelegate::ApplicationClientIdForFileScanning() {
|
|
||||||
return std::string(chrome::kApplicationClientIDStringForAVScanning);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefDownloadManagerDelegate::OnBrowserDestroyed(
|
|
||||||
CefBrowserHostBase* browser) {
|
|
||||||
ItemBrowserMap::iterator it = item_browser_map_.begin();
|
|
||||||
for (; it != item_browser_map_.end(); ++it) {
|
|
||||||
if (it->second == browser) {
|
|
||||||
// Don't call back into browsers that have been destroyed. We're not
|
|
||||||
// canceling the download so it will continue silently until it completes
|
|
||||||
// or until the associated browser context is destroyed.
|
|
||||||
it->second = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AlloyBrowserHostImpl* CefDownloadManagerDelegate::GetOrAssociateBrowser(
|
|
||||||
download::DownloadItem* item) {
|
|
||||||
ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
|
|
||||||
if (it != item_browser_map_.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
AlloyBrowserHostImpl* browser = nullptr;
|
|
||||||
content::WebContents* contents =
|
|
||||||
content::DownloadItemUtils::GetWebContents(item);
|
|
||||||
if (contents) {
|
|
||||||
browser = AlloyBrowserHostImpl::GetBrowserForContents(contents).get();
|
|
||||||
DCHECK(browser);
|
|
||||||
}
|
|
||||||
if (!browser) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
item->AddObserver(this);
|
|
||||||
|
|
||||||
item_browser_map_.insert(std::make_pair(item, browser));
|
|
||||||
|
|
||||||
// Register as an observer so that we can cancel associated DownloadItems when
|
|
||||||
// the browser is destroyed.
|
|
||||||
if (!browser->HasObserver(this)) {
|
|
||||||
browser->AddObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
AlloyBrowserHostImpl* CefDownloadManagerDelegate::GetBrowser(
|
|
||||||
DownloadItem* item) {
|
|
||||||
ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
|
|
||||||
if (it != item_browser_map_.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
|
||||||
// then an "interrupted" download will be started via DownloadManagerImpl::
|
|
||||||
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
|
||||||
// associated WebContents and consequently no associated CEF browser. In that
|
|
||||||
// case DetermineDownloadTarget will be called before OnDownloadCreated.
|
|
||||||
DCHECK(!content::DownloadItemUtils::GetWebContents(item));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
@ -1,68 +1,33 @@
|
|||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
// Copyright 2024 The Chromium Embedded Framework Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
// found in the LICENSE file.
|
// in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
#ifndef CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
||||||
#define CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
#define CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <set>
|
#include <memory>
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_base.h"
|
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
|
||||||
#include "components/download/public/common/download_item.h"
|
|
||||||
#include "components/download/public/common/download_target_info.h"
|
|
||||||
#include "content/public/browser/download_manager.h"
|
|
||||||
#include "content/public/browser/download_manager_delegate.h"
|
#include "content/public/browser/download_manager_delegate.h"
|
||||||
|
|
||||||
class AlloyBrowserHostImpl;
|
namespace content {
|
||||||
|
class DownloadManager;
|
||||||
|
} // namespace content
|
||||||
|
|
||||||
class CefDownloadManagerDelegate : public download::DownloadItem::Observer,
|
namespace cef {
|
||||||
public content::DownloadManager::Observer,
|
|
||||||
public content::DownloadManagerDelegate,
|
class DownloadManagerDelegate : public content::DownloadManagerDelegate {
|
||||||
public CefBrowserHostBase::Observer {
|
|
||||||
public:
|
public:
|
||||||
explicit CefDownloadManagerDelegate(content::DownloadManager* manager);
|
// Called from the ChromeDownloadManagerDelegate constructor for Chrome
|
||||||
|
// bootstrap. Alloy bootstrap uses AlloyDownloadManagerDelegate directly.
|
||||||
CefDownloadManagerDelegate(const CefDownloadManagerDelegate&) = delete;
|
static std::unique_ptr<DownloadManagerDelegate> Create(
|
||||||
CefDownloadManagerDelegate& operator=(const CefDownloadManagerDelegate&) =
|
content::DownloadManager* download_manager);
|
||||||
delete;
|
|
||||||
|
|
||||||
~CefDownloadManagerDelegate() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// DownloadItem::Observer methods.
|
// Allow deletion via std::unique_ptr only.
|
||||||
void OnDownloadUpdated(download::DownloadItem* item) override;
|
friend std::default_delete<DownloadManagerDelegate>;
|
||||||
void OnDownloadDestroyed(download::DownloadItem* item) override;
|
|
||||||
|
|
||||||
// DownloadManager::Observer methods.
|
|
||||||
void OnDownloadCreated(content::DownloadManager* manager,
|
|
||||||
download::DownloadItem* item) override;
|
|
||||||
void ManagerGoingDown(content::DownloadManager* manager) override;
|
|
||||||
|
|
||||||
// DownloadManagerDelegate methods.
|
|
||||||
bool DetermineDownloadTarget(
|
|
||||||
download::DownloadItem* item,
|
|
||||||
download::DownloadTargetCallback* callback) override;
|
|
||||||
void GetNextId(content::DownloadIdCallback callback) override;
|
|
||||||
std::string ApplicationClientIdForFileScanning() override;
|
|
||||||
|
|
||||||
// CefBrowserHostBase::Observer methods.
|
|
||||||
void OnBrowserDestroyed(CefBrowserHostBase* browser) override;
|
|
||||||
|
|
||||||
AlloyBrowserHostImpl* GetOrAssociateBrowser(download::DownloadItem* item);
|
|
||||||
AlloyBrowserHostImpl* GetBrowser(download::DownloadItem* item);
|
|
||||||
|
|
||||||
content::DownloadManager* manager_;
|
|
||||||
base::WeakPtrFactory<content::DownloadManager> manager_ptr_factory_;
|
|
||||||
|
|
||||||
// Map of DownloadItem to originating AlloyBrowserHostImpl. Maintaining this
|
|
||||||
// map is necessary because DownloadItem::GetWebContents() may return NULL if
|
|
||||||
// the browser navigates while the download is in progress.
|
|
||||||
using ItemBrowserMap =
|
|
||||||
std::map<download::DownloadItem*, AlloyBrowserHostImpl*>;
|
|
||||||
ItemBrowserMap item_browser_map_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace cef
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
#endif // CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
|
||||||
|
498
libcef/browser/download_manager_delegate_impl.cc
Normal file
498
libcef/browser/download_manager_delegate_impl.cc
Normal file
@ -0,0 +1,498 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "libcef/browser/download_manager_delegate_impl.h"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "include/cef_download_handler.h"
|
||||||
|
#include "libcef/browser/browser_host_base.h"
|
||||||
|
#include "libcef/browser/context.h"
|
||||||
|
#include "libcef/browser/download_item_impl.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
|
#include "base/files/file_util.h"
|
||||||
|
#include "base/functional/bind.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/path_service.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "content/public/browser/browser_context.h"
|
||||||
|
#include "content/public/browser/download_item_utils.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "net/base/filename_util.h"
|
||||||
|
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
||||||
|
|
||||||
|
using content::DownloadManager;
|
||||||
|
using content::WebContents;
|
||||||
|
using download::DownloadItem;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Helper function to retrieve the CefDownloadHandler.
|
||||||
|
CefRefPtr<CefDownloadHandler> GetDownloadHandler(
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser) {
|
||||||
|
CefRefPtr<CefClient> client = browser->GetClient();
|
||||||
|
if (client.get()) {
|
||||||
|
return client->GetDownloadHandler();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunDownloadTargetCallback(download::DownloadTargetCallback callback,
|
||||||
|
const base::FilePath& path) {
|
||||||
|
download::DownloadTargetInfo target_info;
|
||||||
|
target_info.target_path = path;
|
||||||
|
target_info.intermediate_path = path;
|
||||||
|
std::move(callback).Run(std::move(target_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CefBeforeDownloadCallback implementation.
|
||||||
|
class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
||||||
|
public:
|
||||||
|
CefBeforeDownloadCallbackImpl(const base::WeakPtr<DownloadManager>& manager,
|
||||||
|
uint32_t download_id,
|
||||||
|
const base::FilePath& suggested_name,
|
||||||
|
download::DownloadTargetCallback callback)
|
||||||
|
: manager_(manager),
|
||||||
|
download_id_(download_id),
|
||||||
|
suggested_name_(suggested_name),
|
||||||
|
callback_(std::move(callback)) {}
|
||||||
|
|
||||||
|
CefBeforeDownloadCallbackImpl(const CefBeforeDownloadCallbackImpl&) = delete;
|
||||||
|
CefBeforeDownloadCallbackImpl& operator=(
|
||||||
|
const CefBeforeDownloadCallbackImpl&) = delete;
|
||||||
|
|
||||||
|
void Continue(const CefString& download_path, bool show_dialog) override {
|
||||||
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
if (download_id_ <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager_) {
|
||||||
|
base::FilePath path = base::FilePath(download_path);
|
||||||
|
CEF_POST_USER_VISIBLE_TASK(
|
||||||
|
base::BindOnce(&CefBeforeDownloadCallbackImpl::GenerateFilename,
|
||||||
|
manager_, download_id_, suggested_name_, path,
|
||||||
|
show_dialog, std::move(callback_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
download_id_ = 0;
|
||||||
|
} else {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::BindOnce(&CefBeforeDownloadCallbackImpl::Continue,
|
||||||
|
this, download_path, show_dialog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDetached() const { return callback_.is_null(); }
|
||||||
|
[[nodiscard]] download::DownloadTargetCallback Detach() {
|
||||||
|
return std::move(callback_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void GenerateFilename(base::WeakPtr<DownloadManager> manager,
|
||||||
|
uint32_t download_id,
|
||||||
|
const base::FilePath& suggested_name,
|
||||||
|
const base::FilePath& download_path,
|
||||||
|
bool show_dialog,
|
||||||
|
download::DownloadTargetCallback callback) {
|
||||||
|
CEF_REQUIRE_BLOCKING();
|
||||||
|
|
||||||
|
base::FilePath suggested_path = download_path;
|
||||||
|
if (!suggested_path.empty()) {
|
||||||
|
// Create the directory if necessary.
|
||||||
|
base::FilePath dir_path = suggested_path.DirName();
|
||||||
|
if (!base::DirectoryExists(dir_path) &&
|
||||||
|
!base::CreateDirectory(dir_path)) {
|
||||||
|
DCHECK(false) << "failed to create the download directory";
|
||||||
|
suggested_path.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggested_path.empty()) {
|
||||||
|
if (base::PathService::Get(base::DIR_TEMP, &suggested_path)) {
|
||||||
|
// Use the temp directory.
|
||||||
|
suggested_path = suggested_path.Append(suggested_name);
|
||||||
|
} else {
|
||||||
|
// Use the current working directory.
|
||||||
|
suggested_path = suggested_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CEF_POST_TASK(
|
||||||
|
CEF_UIT,
|
||||||
|
base::BindOnce(&CefBeforeDownloadCallbackImpl::ChooseDownloadPath,
|
||||||
|
manager, download_id, suggested_path, show_dialog,
|
||||||
|
std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ChooseDownloadPath(base::WeakPtr<DownloadManager> manager,
|
||||||
|
uint32_t download_id,
|
||||||
|
const base::FilePath& suggested_path,
|
||||||
|
bool show_dialog,
|
||||||
|
download::DownloadTargetCallback callback) {
|
||||||
|
if (!manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadItem* item = manager->GetDownload(download_id);
|
||||||
|
if (!item || item->GetState() != DownloadItem::IN_PROGRESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
if (show_dialog) {
|
||||||
|
WebContents* web_contents =
|
||||||
|
content::DownloadItemUtils::GetWebContents(item);
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser =
|
||||||
|
CefBrowserHostBase::GetBrowserForContents(web_contents);
|
||||||
|
if (browser.get()) {
|
||||||
|
handled = true;
|
||||||
|
|
||||||
|
blink::mojom::FileChooserParams params;
|
||||||
|
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
||||||
|
if (!suggested_path.empty()) {
|
||||||
|
params.default_file_name = suggested_path;
|
||||||
|
if (!suggested_path.Extension().empty()) {
|
||||||
|
params.accept_types.push_back(
|
||||||
|
CefString(suggested_path.Extension()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser->RunFileChooserForBrowser(
|
||||||
|
params,
|
||||||
|
base::BindOnce(
|
||||||
|
&CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
|
||||||
|
std::move(callback)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
RunDownloadTargetCallback(std::move(callback), suggested_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ChooseDownloadPathCallback(
|
||||||
|
download::DownloadTargetCallback callback,
|
||||||
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
|
DCHECK_LE(file_paths.size(), (size_t)1);
|
||||||
|
|
||||||
|
base::FilePath path;
|
||||||
|
if (file_paths.size() > 0) {
|
||||||
|
path = file_paths.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The download will be cancelled if |path| is empty.
|
||||||
|
RunDownloadTargetCallback(std::move(callback), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
base::WeakPtr<DownloadManager> manager_;
|
||||||
|
uint32_t download_id_;
|
||||||
|
base::FilePath suggested_name_;
|
||||||
|
download::DownloadTargetCallback callback_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(CefBeforeDownloadCallbackImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// CefDownloadItemCallback implementation.
|
||||||
|
class CefDownloadItemCallbackImpl : public CefDownloadItemCallback {
|
||||||
|
public:
|
||||||
|
explicit CefDownloadItemCallbackImpl(
|
||||||
|
const base::WeakPtr<DownloadManager>& manager,
|
||||||
|
uint32_t download_id)
|
||||||
|
: manager_(manager), download_id_(download_id) {}
|
||||||
|
|
||||||
|
CefDownloadItemCallbackImpl(const CefDownloadItemCallbackImpl&) = delete;
|
||||||
|
CefDownloadItemCallbackImpl& operator=(const CefDownloadItemCallbackImpl&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
void Cancel() override {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::BindOnce(&CefDownloadItemCallbackImpl::DoCancel, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pause() override {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::BindOnce(&CefDownloadItemCallbackImpl::DoPause, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resume() override {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::BindOnce(&CefDownloadItemCallbackImpl::DoResume, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DoCancel() {
|
||||||
|
if (download_id_ <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager_) {
|
||||||
|
DownloadItem* item = manager_->GetDownload(download_id_);
|
||||||
|
if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
|
||||||
|
item->Cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
download_id_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoPause() {
|
||||||
|
if (download_id_ <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager_) {
|
||||||
|
DownloadItem* item = manager_->GetDownload(download_id_);
|
||||||
|
if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
|
||||||
|
item->Pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoResume() {
|
||||||
|
if (download_id_ <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager_) {
|
||||||
|
DownloadItem* item = manager_->GetDownload(download_id_);
|
||||||
|
if (item && item->CanResume()) {
|
||||||
|
item->Resume(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base::WeakPtr<DownloadManager> manager_;
|
||||||
|
uint32_t download_id_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(CefDownloadItemCallbackImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefDownloadManagerDelegateImpl::CefDownloadManagerDelegateImpl(
|
||||||
|
DownloadManager* manager,
|
||||||
|
bool alloy_bootstrap)
|
||||||
|
: manager_(manager),
|
||||||
|
manager_ptr_factory_(manager),
|
||||||
|
alloy_bootstrap_(alloy_bootstrap) {
|
||||||
|
DCHECK(manager);
|
||||||
|
manager->AddObserver(this);
|
||||||
|
|
||||||
|
DownloadManager::DownloadVector items;
|
||||||
|
manager->GetAllDownloads(&items);
|
||||||
|
DownloadManager::DownloadVector::const_iterator it = items.begin();
|
||||||
|
for (; it != items.end(); ++it) {
|
||||||
|
OnDownloadCreated(manager, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefDownloadManagerDelegateImpl::~CefDownloadManagerDelegateImpl() {
|
||||||
|
ResetManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::OnDownloadUpdated(DownloadItem* download) {
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser = GetBrowser(download);
|
||||||
|
CefRefPtr<CefDownloadHandler> handler;
|
||||||
|
if (browser.get()) {
|
||||||
|
handler = GetDownloadHandler(browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler.get()) {
|
||||||
|
CefRefPtr<CefDownloadItemImpl> download_item(
|
||||||
|
new CefDownloadItemImpl(download));
|
||||||
|
CefRefPtr<CefDownloadItemCallback> callback(new CefDownloadItemCallbackImpl(
|
||||||
|
manager_ptr_factory_.GetWeakPtr(), download->GetId()));
|
||||||
|
|
||||||
|
handler->OnDownloadUpdated(browser.get(), download_item.get(), callback);
|
||||||
|
|
||||||
|
std::ignore = download_item->Detach(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::OnDownloadDestroyed(DownloadItem* item) {
|
||||||
|
item->RemoveObserver(this);
|
||||||
|
|
||||||
|
CefBrowserHostBase* browser = nullptr;
|
||||||
|
|
||||||
|
ItemBrowserMap::iterator it = item_browser_map_.find(item);
|
||||||
|
DCHECK(it != item_browser_map_.end());
|
||||||
|
if (it != item_browser_map_.end()) {
|
||||||
|
browser = it->second;
|
||||||
|
item_browser_map_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (browser) {
|
||||||
|
// Determine if any remaining DownloadItems are associated with the same
|
||||||
|
// browser. If not, then unregister as an observer.
|
||||||
|
bool has_remaining = false;
|
||||||
|
ItemBrowserMap::const_iterator it2 = item_browser_map_.begin();
|
||||||
|
for (; it2 != item_browser_map_.end(); ++it2) {
|
||||||
|
if (it2->second == browser) {
|
||||||
|
has_remaining = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_remaining) {
|
||||||
|
browser->RemoveObserver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::OnDownloadCreated(DownloadManager* manager,
|
||||||
|
DownloadItem* item) {
|
||||||
|
// This callback may arrive after DetermineDownloadTarget, so we allow
|
||||||
|
// association from either method.
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser = GetOrAssociateBrowser(item);
|
||||||
|
if (!browser) {
|
||||||
|
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
||||||
|
// then an "interrupted" download will be started via DownloadManagerImpl::
|
||||||
|
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
||||||
|
// associated WebContents and consequently no associated CEF browser. In
|
||||||
|
// that case DetermineDownloadTarget will be called before this method.
|
||||||
|
// TODO(cef): Figure out how to expose this via a client callback.
|
||||||
|
const std::vector<GURL>& url_chain = item->GetUrlChain();
|
||||||
|
if (!url_chain.empty()) {
|
||||||
|
LOG(INFO) << "Rejected download of " << url_chain.back().spec();
|
||||||
|
}
|
||||||
|
item->Cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::ManagerGoingDown(
|
||||||
|
DownloadManager* manager) {
|
||||||
|
DCHECK_EQ(manager, manager_);
|
||||||
|
ResetManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefDownloadManagerDelegateImpl::DetermineDownloadTarget(
|
||||||
|
DownloadItem* item,
|
||||||
|
download::DownloadTargetCallback* callback) {
|
||||||
|
if (alloy_bootstrap_) {
|
||||||
|
const auto& forced_path = item->GetForcedFilePath();
|
||||||
|
if (!forced_path.empty()) {
|
||||||
|
RunDownloadTargetCallback(std::move(*callback), forced_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This callback may arrive before OnDownloadCreated, so we allow association
|
||||||
|
// from either method.
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser = GetOrAssociateBrowser(item);
|
||||||
|
if (!browser) {
|
||||||
|
// Cancel by default with Alloy bootstrap.
|
||||||
|
return alloy_bootstrap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
CefRefPtr<CefDownloadHandler> handler = GetDownloadHandler(browser);
|
||||||
|
if (handler) {
|
||||||
|
base::FilePath suggested_name = net::GenerateFileName(
|
||||||
|
item->GetURL(), item->GetContentDisposition(), std::string(),
|
||||||
|
item->GetSuggestedFilename(), item->GetMimeType(), "download");
|
||||||
|
|
||||||
|
CefRefPtr<CefDownloadItemImpl> download_item(new CefDownloadItemImpl(item));
|
||||||
|
CefRefPtr<CefBeforeDownloadCallbackImpl> callbackObj(
|
||||||
|
new CefBeforeDownloadCallbackImpl(manager_ptr_factory_.GetWeakPtr(),
|
||||||
|
item->GetId(), suggested_name,
|
||||||
|
std::move(*callback)));
|
||||||
|
|
||||||
|
handled =
|
||||||
|
handler->OnBeforeDownload(browser.get(), download_item.get(),
|
||||||
|
suggested_name.value(), callbackObj.get());
|
||||||
|
if (!handled && callbackObj->IsDetached()) {
|
||||||
|
LOG(ERROR) << "Should return true from OnBeforeDownload when executing "
|
||||||
|
"the callback";
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
if (!handled) {
|
||||||
|
*callback = callbackObj->Detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ignore = download_item->Detach(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel by default with Alloy style.
|
||||||
|
return handled ? true : alloy_bootstrap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::OnBrowserDestroyed(
|
||||||
|
CefBrowserHostBase* browser) {
|
||||||
|
ItemBrowserMap::iterator it = item_browser_map_.begin();
|
||||||
|
for (; it != item_browser_map_.end(); ++it) {
|
||||||
|
if (it->second == browser) {
|
||||||
|
// Don't call back into browsers that have been destroyed. We're not
|
||||||
|
// canceling the download so it will continue silently until it completes
|
||||||
|
// or until the associated browser context is destroyed.
|
||||||
|
it->second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase>
|
||||||
|
CefDownloadManagerDelegateImpl::GetOrAssociateBrowser(
|
||||||
|
download::DownloadItem* item) {
|
||||||
|
ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
|
||||||
|
if (it != item_browser_map_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser;
|
||||||
|
content::WebContents* contents =
|
||||||
|
content::DownloadItemUtils::GetWebContents(item);
|
||||||
|
if (contents) {
|
||||||
|
browser = CefBrowserHostBase::GetBrowserForContents(contents);
|
||||||
|
LOG_IF(WARNING, !browser) << "No CefBrowser for download item";
|
||||||
|
}
|
||||||
|
if (!browser) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->AddObserver(this);
|
||||||
|
|
||||||
|
item_browser_map_.insert(std::make_pair(item, browser.get()));
|
||||||
|
|
||||||
|
// Register as an observer so that we can cancel associated DownloadItems when
|
||||||
|
// the browser is destroyed.
|
||||||
|
if (!browser->HasObserver(this)) {
|
||||||
|
browser->AddObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> CefDownloadManagerDelegateImpl::GetBrowser(
|
||||||
|
DownloadItem* item) {
|
||||||
|
ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
|
||||||
|
if (it != item_browser_map_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
||||||
|
// then an "interrupted" download will be started via DownloadManagerImpl::
|
||||||
|
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
||||||
|
// associated WebContents and consequently no associated CEF browser. In that
|
||||||
|
// case DetermineDownloadTarget will be called before OnDownloadCreated.
|
||||||
|
DCHECK(!content::DownloadItemUtils::GetWebContents(item));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefDownloadManagerDelegateImpl::ResetManager() {
|
||||||
|
if (manager_) {
|
||||||
|
if (alloy_bootstrap_) {
|
||||||
|
manager_->SetDelegate(nullptr);
|
||||||
|
}
|
||||||
|
manager_->RemoveObserver(this);
|
||||||
|
manager_ptr_factory_.InvalidateWeakPtrs();
|
||||||
|
manager_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!item_browser_map_.empty()) {
|
||||||
|
OnDownloadDestroyed(item_browser_map_.begin()->first);
|
||||||
|
}
|
||||||
|
}
|
72
libcef/browser/download_manager_delegate_impl.h
Normal file
72
libcef/browser/download_manager_delegate_impl.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_IMPL_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_IMPL_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_base.h"
|
||||||
|
#include "libcef/browser/download_manager_delegate.h"
|
||||||
|
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "components/download/public/common/download_item.h"
|
||||||
|
#include "components/download/public/common/download_target_info.h"
|
||||||
|
#include "content/public/browser/download_manager.h"
|
||||||
|
|
||||||
|
class CefBrowserHostBase;
|
||||||
|
|
||||||
|
class CefDownloadManagerDelegateImpl
|
||||||
|
: public download::DownloadItem::Observer,
|
||||||
|
public content::DownloadManager::Observer,
|
||||||
|
public cef::DownloadManagerDelegate,
|
||||||
|
public CefBrowserHostBase::Observer {
|
||||||
|
public:
|
||||||
|
CefDownloadManagerDelegateImpl(content::DownloadManager* manager,
|
||||||
|
bool alloy_bootstrap);
|
||||||
|
|
||||||
|
CefDownloadManagerDelegateImpl(const CefDownloadManagerDelegateImpl&) =
|
||||||
|
delete;
|
||||||
|
CefDownloadManagerDelegateImpl& operator=(
|
||||||
|
const CefDownloadManagerDelegateImpl&) = delete;
|
||||||
|
|
||||||
|
~CefDownloadManagerDelegateImpl() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// DownloadItem::Observer methods.
|
||||||
|
void OnDownloadUpdated(download::DownloadItem* item) override;
|
||||||
|
void OnDownloadDestroyed(download::DownloadItem* item) override;
|
||||||
|
|
||||||
|
// DownloadManager::Observer methods.
|
||||||
|
void OnDownloadCreated(content::DownloadManager* manager,
|
||||||
|
download::DownloadItem* item) override;
|
||||||
|
void ManagerGoingDown(content::DownloadManager* manager) override;
|
||||||
|
|
||||||
|
// DownloadManagerDelegate methods.
|
||||||
|
bool DetermineDownloadTarget(
|
||||||
|
download::DownloadItem* item,
|
||||||
|
download::DownloadTargetCallback* callback) override;
|
||||||
|
|
||||||
|
// CefBrowserHostBase::Observer methods.
|
||||||
|
void OnBrowserDestroyed(CefBrowserHostBase* browser) override;
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> GetOrAssociateBrowser(
|
||||||
|
download::DownloadItem* item);
|
||||||
|
CefRefPtr<CefBrowserHostBase> GetBrowser(download::DownloadItem* item);
|
||||||
|
|
||||||
|
void ResetManager();
|
||||||
|
|
||||||
|
content::DownloadManager* manager_;
|
||||||
|
base::WeakPtrFactory<content::DownloadManager> manager_ptr_factory_;
|
||||||
|
const bool alloy_bootstrap_;
|
||||||
|
|
||||||
|
// Map of DownloadItem to originating CefBrowserHostBase. Maintaining this
|
||||||
|
// map is necessary because DownloadItem::GetWebContents() may return NULL if
|
||||||
|
// the browser navigates while the download is in progress.
|
||||||
|
using ItemBrowserMap = std::map<download::DownloadItem*, CefBrowserHostBase*>;
|
||||||
|
ItemBrowserMap item_browser_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_IMPL_H_
|
@ -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=c70a949d129e47d660f9fd4200db05e2f5721bed$
|
// $hash=f310399ebf0026717b1d733a34dd51b90623c452$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
|
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
|
||||||
@ -61,7 +61,7 @@ download_handler_can_download(struct _cef_download_handler_t* self,
|
|||||||
return _retval;
|
return _retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK
|
int 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,
|
||||||
struct _cef_download_item_t* download_item,
|
struct _cef_download_item_t* download_item,
|
||||||
@ -73,34 +73,37 @@ download_handler_on_before_download(struct _cef_download_handler_t* self,
|
|||||||
|
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
// Verify param: browser; type: refptr_diff
|
// Verify param: browser; type: refptr_diff
|
||||||
DCHECK(browser);
|
DCHECK(browser);
|
||||||
if (!browser) {
|
if (!browser) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
// Verify param: download_item; type: refptr_diff
|
// Verify param: download_item; type: refptr_diff
|
||||||
DCHECK(download_item);
|
DCHECK(download_item);
|
||||||
if (!download_item) {
|
if (!download_item) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
// Verify param: suggested_name; type: string_byref_const
|
// Verify param: suggested_name; type: string_byref_const
|
||||||
DCHECK(suggested_name);
|
DCHECK(suggested_name);
|
||||||
if (!suggested_name) {
|
if (!suggested_name) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback);
|
DCHECK(callback);
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefDownloadHandlerCppToC::Get(self)->OnBeforeDownload(
|
bool _retval = CefDownloadHandlerCppToC::Get(self)->OnBeforeDownload(
|
||||||
CefBrowserCToCpp::Wrap(browser),
|
CefBrowserCToCpp::Wrap(browser),
|
||||||
CefDownloadItemCToCpp::Wrap(download_item), CefString(suggested_name),
|
CefDownloadItemCToCpp::Wrap(download_item), CefString(suggested_name),
|
||||||
CefBeforeDownloadCallbackCToCpp::Wrap(callback));
|
CefBeforeDownloadCallbackCToCpp::Wrap(callback));
|
||||||
|
|
||||||
|
// Return type: bool
|
||||||
|
return _retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK
|
void CEF_CALLBACK
|
||||||
|
@ -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=690401fe62e7a96ea1c2d72b48144f789207e204$
|
// $hash=6c28836de30002d764d9dcab7f51260cc447f639$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
|
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
|
||||||
@ -60,7 +60,7 @@ bool CefDownloadHandlerCToCpp::CanDownload(CefRefPtr<CefBrowser> browser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NO_SANITIZE("cfi-icall")
|
NO_SANITIZE("cfi-icall")
|
||||||
void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
bool CefDownloadHandlerCToCpp::OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
@ -69,7 +69,7 @@ void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
|||||||
|
|
||||||
cef_download_handler_t* _struct = GetStruct();
|
cef_download_handler_t* _struct = GetStruct();
|
||||||
if (CEF_MEMBER_MISSING(_struct, on_before_download)) {
|
if (CEF_MEMBER_MISSING(_struct, on_before_download)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
@ -77,29 +77,32 @@ void CefDownloadHandlerCToCpp::OnBeforeDownload(
|
|||||||
// Verify param: browser; type: refptr_diff
|
// Verify param: browser; type: refptr_diff
|
||||||
DCHECK(browser.get());
|
DCHECK(browser.get());
|
||||||
if (!browser.get()) {
|
if (!browser.get()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// Verify param: download_item; type: refptr_diff
|
// Verify param: download_item; type: refptr_diff
|
||||||
DCHECK(download_item.get());
|
DCHECK(download_item.get());
|
||||||
if (!download_item.get()) {
|
if (!download_item.get()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// Verify param: suggested_name; type: string_byref_const
|
// Verify param: suggested_name; type: string_byref_const
|
||||||
DCHECK(!suggested_name.empty());
|
DCHECK(!suggested_name.empty());
|
||||||
if (suggested_name.empty()) {
|
if (suggested_name.empty()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get()) {
|
if (!callback.get()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
_struct->on_before_download(_struct, CefBrowserCppToC::Wrap(browser),
|
int _retval = _struct->on_before_download(
|
||||||
CefDownloadItemCppToC::Wrap(download_item),
|
_struct, CefBrowserCppToC::Wrap(browser),
|
||||||
suggested_name.GetStruct(),
|
CefDownloadItemCppToC::Wrap(download_item), suggested_name.GetStruct(),
|
||||||
CefBeforeDownloadCallbackCppToC::Wrap(callback));
|
CefBeforeDownloadCallbackCppToC::Wrap(callback));
|
||||||
|
|
||||||
|
// Return type: bool
|
||||||
|
return _retval ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NO_SANITIZE("cfi-icall")
|
NO_SANITIZE("cfi-icall")
|
||||||
|
@ -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=13fc7d443a6c044598f0683e235f682d91798042$
|
// $hash=fbf27fd04a17a31cb8d279b8a8e1381c7858bc2c$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
|
||||||
@ -38,7 +38,7 @@ class CefDownloadHandlerCToCpp
|
|||||||
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
const CefString& url,
|
const CefString& url,
|
||||||
const CefString& request_method) override;
|
const CefString& request_method) override;
|
||||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
bool OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
CefRefPtr<CefBeforeDownloadCallback> callback) override;
|
CefRefPtr<CefBeforeDownloadCallback> callback) override;
|
||||||
|
@ -279,6 +279,12 @@ patches = [
|
|||||||
# https://chromium-review.googlesource.com/c/chromium/src/+/5006355
|
# https://chromium-review.googlesource.com/c/chromium/src/+/5006355
|
||||||
'name': 'chrome_browser_dialogs_widget',
|
'name': 'chrome_browser_dialogs_widget',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
# alloy: Support override of DownloadPrefs::FromBrowserContext
|
||||||
|
# chrome: Support custom DownloadManagerDelegate handling.
|
||||||
|
# https://github.com/chromiumembedded/cef/issues/3681
|
||||||
|
'name': 'chrome_browser_download',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
# chrome: Support override of ChromeMimeHandlerViewGuestDelegate.
|
# chrome: Support override of ChromeMimeHandlerViewGuestDelegate.
|
||||||
# https://github.com/chromiumembedded/cef/issues/2969
|
# https://github.com/chromiumembedded/cef/issues/2969
|
||||||
|
121
patch/patches/chrome_browser_download.patch
Normal file
121
patch/patches/chrome_browser_download.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
diff --git chrome/browser/download/chrome_download_manager_delegate.cc chrome/browser/download/chrome_download_manager_delegate.cc
|
||||||
|
index 447e7d0d5dc6d..7bba632f1331c 100644
|
||||||
|
--- chrome/browser/download/chrome_download_manager_delegate.cc
|
||||||
|
+++ chrome/browser/download/chrome_download_manager_delegate.cc
|
||||||
|
@@ -146,6 +146,10 @@
|
||||||
|
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+#include "cef/libcef/browser/download_manager_delegate.h"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
using content::BrowserThread;
|
||||||
|
using content::DownloadManager;
|
||||||
|
using download::DownloadItem;
|
||||||
|
@@ -490,6 +494,11 @@ ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile)
|
||||||
|
download_dialog_bridge_ = std::make_unique<DownloadDialogBridge>();
|
||||||
|
download_message_bridge_ = std::make_unique<DownloadMessageBridge>();
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ cef_delegate_ =
|
||||||
|
+ cef::DownloadManagerDelegate::Create(profile_->GetDownloadManager());
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
|
||||||
|
@@ -549,6 +558,9 @@ void ChromeDownloadManagerDelegate::Shutdown() {
|
||||||
|
download_manager_->RemoveObserver(this);
|
||||||
|
download_manager_ = nullptr;
|
||||||
|
}
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ cef_delegate_.reset();
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChromeDownloadManagerDelegate::OnDownloadCanceledAtShutdown(
|
||||||
|
@@ -617,6 +629,12 @@ bool ChromeDownloadManagerDelegate::DetermineDownloadTarget(
|
||||||
|
ReportPDFLoadStatus(PDFLoadStatus::kTriggeredNoGestureDriveByDownload);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ if (cef_delegate_->DetermineDownloadTarget(download, callback)) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
DownloadTargetDeterminer::CompletionCallback target_determined_callback =
|
||||||
|
base::BindOnce(&ChromeDownloadManagerDelegate::OnDownloadTargetDetermined,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), download->GetId(),
|
||||||
|
diff --git chrome/browser/download/chrome_download_manager_delegate.h chrome/browser/download/chrome_download_manager_delegate.h
|
||||||
|
index e2cf12d2c8fee..376818e28798c 100644
|
||||||
|
--- chrome/browser/download/chrome_download_manager_delegate.h
|
||||||
|
+++ chrome/browser/download/chrome_download_manager_delegate.h
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
#include "base/task/sequenced_task_runner.h"
|
||||||
|
#include "base/unguessable_token.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
+#include "cef/libcef/features/runtime.h"
|
||||||
|
#include "chrome/browser/download/download_completion_blocker.h"
|
||||||
|
#include "chrome/browser/download/download_target_determiner_delegate.h"
|
||||||
|
#include "components/download/public/common/download_danger_type.h"
|
||||||
|
@@ -57,6 +58,12 @@ class CrxInstallError;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+namespace cef {
|
||||||
|
+class DownloadManagerDelegate;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
// This is the Chrome side helper for the download system.
|
||||||
|
class ChromeDownloadManagerDelegate
|
||||||
|
: public content::DownloadManagerDelegate,
|
||||||
|
@@ -387,6 +394,10 @@ class ChromeDownloadManagerDelegate
|
||||||
|
// Whether a file picker dialog is showing.
|
||||||
|
bool is_file_picker_showing_;
|
||||||
|
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ std::unique_ptr<cef::DownloadManagerDelegate> cef_delegate_;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
base::WeakPtrFactory<ChromeDownloadManagerDelegate> weak_ptr_factory_{this};
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git chrome/browser/download/download_prefs.cc chrome/browser/download/download_prefs.cc
|
||||||
|
index 773f72da82f90..6d0307988406f 100644
|
||||||
|
--- chrome/browser/download/download_prefs.cc
|
||||||
|
+++ chrome/browser/download/download_prefs.cc
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "build/chromeos_buildflags.h"
|
||||||
|
+#include "cef/libcef/features/runtime.h"
|
||||||
|
#include "chrome/browser/download/chrome_download_manager_delegate.h"
|
||||||
|
#include "chrome/browser/download/download_core_service_factory.h"
|
||||||
|
#include "chrome/browser/download/download_core_service_impl.h"
|
||||||
|
@@ -64,6 +65,10 @@
|
||||||
|
#include "chrome/browser/flags/android/chrome_feature_list.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+#include "cef/libcef/browser/alloy/alloy_download_util.h"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
using content::BrowserContext;
|
||||||
|
using content::BrowserThread;
|
||||||
|
using content::DownloadManager;
|
||||||
|
@@ -355,6 +360,11 @@ DownloadPrefs* DownloadPrefs::FromDownloadManager(
|
||||||
|
// static
|
||||||
|
DownloadPrefs* DownloadPrefs::FromBrowserContext(
|
||||||
|
content::BrowserContext* context) {
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ if (cef::IsAlloyRuntimeEnabled()) {
|
||||||
|
+ return alloy::GetDownloadPrefsFromBrowserContext(context);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
return FromDownloadManager(context->GetDownloadManager());
|
||||||
|
}
|
||||||
|
|
@ -186,3 +186,18 @@ index 2f769363f8519..228c20926634b 100644
|
|||||||
// FYI: Do NOT add any more friends here. The functions above are the ONLY
|
// FYI: Do NOT add any more friends here. The functions above are the ONLY
|
||||||
// ones that need to call AttachTabHelpers; if you think you do, re-read the
|
// ones that need to call AttachTabHelpers; if you think you do, re-read the
|
||||||
// design document linked above, especially the section "Reusing tab helpers".
|
// design document linked above, especially the section "Reusing tab helpers".
|
||||||
|
diff --git chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
|
||||||
|
index a76c331ec5344..ffe3cbe7ce37c 100644
|
||||||
|
--- chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
|
||||||
|
+++ chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
|
||||||
|
@@ -850,6 +850,10 @@ void DownloadToolbarButtonView::ShowPendingDownloadStartedAnimation() {
|
||||||
|
if (!gfx::Animation::ShouldRenderRichAnimation()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
+ if (!IsDrawn()) {
|
||||||
|
+ // Don't animate with a hidden download button.
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
content::WebContents* const web_contents =
|
||||||
|
browser_->tab_strip_model()->GetActiveWebContents();
|
||||||
|
if (!web_contents ||
|
||||||
|
@ -1,38 +1,3 @@
|
|||||||
diff --git chrome/browser/download/download_prefs.cc chrome/browser/download/download_prefs.cc
|
|
||||||
index 773f72da82f90..6d0307988406f 100644
|
|
||||||
--- chrome/browser/download/download_prefs.cc
|
|
||||||
+++ chrome/browser/download/download_prefs.cc
|
|
||||||
@@ -23,6 +23,7 @@
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
|
||||||
#include "build/build_config.h"
|
|
||||||
#include "build/chromeos_buildflags.h"
|
|
||||||
+#include "cef/libcef/features/runtime.h"
|
|
||||||
#include "chrome/browser/download/chrome_download_manager_delegate.h"
|
|
||||||
#include "chrome/browser/download/download_core_service_factory.h"
|
|
||||||
#include "chrome/browser/download/download_core_service_impl.h"
|
|
||||||
@@ -64,6 +65,10 @@
|
|
||||||
#include "chrome/browser/flags/android/chrome_feature_list.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+#include "cef/libcef/browser/alloy/alloy_download_util.h"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
using content::BrowserContext;
|
|
||||||
using content::BrowserThread;
|
|
||||||
using content::DownloadManager;
|
|
||||||
@@ -355,6 +360,11 @@ DownloadPrefs* DownloadPrefs::FromDownloadManager(
|
|
||||||
// static
|
|
||||||
DownloadPrefs* DownloadPrefs::FromBrowserContext(
|
|
||||||
content::BrowserContext* context) {
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ if (cef::IsAlloyRuntimeEnabled()) {
|
|
||||||
+ return alloy::GetDownloadPrefsFromBrowserContext(context);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
return FromDownloadManager(context->GetDownloadManager());
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git chrome/browser/printing/print_preview_dialog_controller.cc chrome/browser/printing/print_preview_dialog_controller.cc
|
diff --git chrome/browser/printing/print_preview_dialog_controller.cc chrome/browser/printing/print_preview_dialog_controller.cc
|
||||||
index 54efe456fd86e..a685c4e0722cc 100644
|
index 54efe456fd86e..a685c4e0722cc 100644
|
||||||
--- chrome/browser/printing/print_preview_dialog_controller.cc
|
--- chrome/browser/printing/print_preview_dialog_controller.cc
|
||||||
|
@ -858,7 +858,7 @@ bool ClientHandler::CanDownload(CefRefPtr<CefBrowser> browser,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientHandler::OnBeforeDownload(
|
bool ClientHandler::OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
@ -867,6 +867,7 @@ void ClientHandler::OnBeforeDownload(
|
|||||||
|
|
||||||
// Continue the download and show the "Save As" dialog.
|
// Continue the download and show the "Save As" dialog.
|
||||||
callback->Continue(MainContext::Get()->GetDownloadPath(suggested_name), true);
|
callback->Continue(MainContext::Get()->GetDownloadPath(suggested_name), true);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientHandler::OnDownloadUpdated(
|
void ClientHandler::OnDownloadUpdated(
|
||||||
|
@ -182,7 +182,7 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
const CefString& url,
|
const CefString& url,
|
||||||
const CefString& request_method) override;
|
const CefString& request_method) override;
|
||||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
bool OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
CefRefPtr<CefBeforeDownloadCallback> callback) override;
|
CefRefPtr<CefBeforeDownloadCallback> callback) override;
|
||||||
|
@ -49,7 +49,7 @@ class DownloadSchemeHandler : public CefResourceHandler {
|
|||||||
content_disposition_ = kTestContentDisposition;
|
content_disposition_ = kTestContentDisposition;
|
||||||
should_delay_ = true;
|
should_delay_ = true;
|
||||||
} else {
|
} else {
|
||||||
EXPECT_TRUE(false); // Not reached.
|
EXPECT_TRUE(IgnoreURL(url)) << url;
|
||||||
|
|
||||||
// Cancel immediately.
|
// Cancel immediately.
|
||||||
handle_request = true;
|
handle_request = true;
|
||||||
@ -187,6 +187,8 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
test_mode_ == CLICKED_BLOCKED;
|
test_mode_ == CLICKED_BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_clicked_invalid() const { return test_mode_ == CLICKED_INVALID; }
|
||||||
|
|
||||||
bool is_clicked_and_downloaded() const { return test_mode_ == CLICKED; }
|
bool is_clicked_and_downloaded() const { return test_mode_ == CLICKED; }
|
||||||
|
|
||||||
bool is_downloaded() const {
|
bool is_downloaded() const {
|
||||||
@ -276,6 +278,14 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
// 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_INVALID ? EVENTFLAG_ALT_DOWN : 0);
|
test_mode_ == CLICKED_INVALID ? EVENTFLAG_ALT_DOWN : 0);
|
||||||
|
|
||||||
|
if (IsChromeBootstrap() && is_clicked_invalid()) {
|
||||||
|
// Destroy the test after a bit because there will be no further
|
||||||
|
// callbacks.
|
||||||
|
CefPostDelayedTask(
|
||||||
|
TID_UI, base::BindOnce(&DownloadTestHandler::DestroyTest, this),
|
||||||
|
200);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Begin the download progammatically.
|
// Begin the download progammatically.
|
||||||
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
||||||
@ -343,7 +353,7 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
return test_mode_ != CLICKED_BLOCKED;
|
return test_mode_ != CLICKED_BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnBeforeDownload(
|
bool OnBeforeDownload(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
CefRefPtr<CefDownloadItem> download_item,
|
||||||
const CefString& suggested_name,
|
const CefString& suggested_name,
|
||||||
@ -393,6 +403,8 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
} else if (test_mode_ == PENDING) {
|
} else if (test_mode_ == PENDING) {
|
||||||
ContinuePendingIfReady();
|
ContinuePendingIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
|
void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
|
||||||
@ -500,7 +512,14 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
CefRegisterSchemeHandlerFactory("https", kTestDomain, nullptr);
|
CefRegisterSchemeHandlerFactory("https", kTestDomain, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_clicked()) {
|
if (is_clicked_invalid()) {
|
||||||
|
if (IsChromeBootstrap()) {
|
||||||
|
// No CanDownload for invalid protocol links.
|
||||||
|
EXPECT_FALSE(got_can_download_);
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(got_can_download_);
|
||||||
|
}
|
||||||
|
} else if (is_clicked()) {
|
||||||
EXPECT_TRUE(got_can_download_);
|
EXPECT_TRUE(got_can_download_);
|
||||||
} else {
|
} else {
|
||||||
EXPECT_FALSE(got_can_download_);
|
EXPECT_FALSE(got_can_download_);
|
||||||
|
@ -150,13 +150,6 @@ class TestHandler : public CefClient,
|
|||||||
CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
|
CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
|
||||||
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
|
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
|
||||||
|
|
||||||
// CefDownloadHandler methods
|
|
||||||
void OnBeforeDownload(
|
|
||||||
CefRefPtr<CefBrowser> browser,
|
|
||||||
CefRefPtr<CefDownloadItem> download_item,
|
|
||||||
const CefString& suggested_name,
|
|
||||||
CefRefPtr<CefBeforeDownloadCallback> callback) override {}
|
|
||||||
|
|
||||||
// CefLifeSpanHandler methods
|
// CefLifeSpanHandler methods
|
||||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
|
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
|
||||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
|
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
|
||||||
|
Reference in New Issue
Block a user