mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01:00
Use Chrome file dialogs on all platforms and runtimes (fixes issue #3314)
All file dialogs irrespective of source, platform and runtime will now be routed through CefFileDialogManager and trigger CefDialogHandler callbacks (see issue #3293). Adds Chrome runtime support for CefBrowserHost::RunFileDialog and CefDialogHandler callbacks. Adds Alloy runtime support for internal GTK file and print dialogs on Linux subject to the following limitations: 1. Internal GTK implementation: - Cannot be used with multi-threaded-message-loop because Chromium's internal GTK implementation is not thread-safe (does not use GDK threads). - Dialogs will not be modal to application windows when used with off-screen rendering due to lack of access to the client's top-level GtkWindow. 2. Cefclient CefDialogHandler implementation: - Cannot be used with Views because it requires a top-level GtkWindow. Due to the above limitations no dialog implementation is currently provided for Views + multi-threaded-message-loop on Linux. In cases where both implementations are supported the cefclient version is now behind an optional `--use-client-dialogs` command-line flag. Expressly forbids multiple simultaneous file dialogs with the internal platform implementation which uses modal dialogs. CefDialogHandler will still be notified and can optionally handle each request without a modal dialog (see issue #3154). Removes some RunFileDialog parameters that are not supported by the Chrome file dialog implementation (selected_accept_filter parameter, cef_file_dialog_mode_t overwrite/read-only flags).
This commit is contained in:
parent
edef01f579
commit
2ea7459a89
9
BUILD.gn
9
BUILD.gn
@ -414,8 +414,6 @@ static_library("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_dialog_util.cc",
|
|
||||||
"libcef/browser/alloy/alloy_dialog_util.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/browser_platform_delegate_alloy.cc",
|
"libcef/browser/alloy/browser_platform_delegate_alloy.cc",
|
||||||
@ -550,9 +548,10 @@ static_library("libcef_static") {
|
|||||||
"libcef/browser/extensions/value_store/cef_value_store.h",
|
"libcef/browser/extensions/value_store/cef_value_store.h",
|
||||||
"libcef/browser/extensions/value_store/cef_value_store_factory.cc",
|
"libcef/browser/extensions/value_store/cef_value_store_factory.cc",
|
||||||
"libcef/browser/extensions/value_store/cef_value_store_factory.h",
|
"libcef/browser/extensions/value_store/cef_value_store_factory.h",
|
||||||
"libcef/browser/file_dialog_runner.h",
|
|
||||||
"libcef/browser/file_dialog_manager.cc",
|
"libcef/browser/file_dialog_manager.cc",
|
||||||
"libcef/browser/file_dialog_manager.h",
|
"libcef/browser/file_dialog_manager.h",
|
||||||
|
"libcef/browser/file_dialog_runner.cc",
|
||||||
|
"libcef/browser/file_dialog_runner.h",
|
||||||
"libcef/browser/frame_host_impl.cc",
|
"libcef/browser/frame_host_impl.cc",
|
||||||
"libcef/browser/frame_host_impl.h",
|
"libcef/browser/frame_host_impl.h",
|
||||||
"libcef/browser/frame_service_base.h",
|
"libcef/browser/frame_service_base.h",
|
||||||
@ -1019,8 +1018,6 @@ static_library("libcef_static") {
|
|||||||
"libcef/browser/native/browser_platform_delegate_native_win.cc",
|
"libcef/browser/native/browser_platform_delegate_native_win.cc",
|
||||||
"libcef/browser/native/browser_platform_delegate_native_win.h",
|
"libcef/browser/native/browser_platform_delegate_native_win.h",
|
||||||
"libcef/browser/native/cursor_util_win.cc",
|
"libcef/browser/native/cursor_util_win.cc",
|
||||||
"libcef/browser/native/file_dialog_runner_win.cc",
|
|
||||||
"libcef/browser/native/file_dialog_runner_win.h",
|
|
||||||
"libcef/browser/native/javascript_dialog_runner_win.cc",
|
"libcef/browser/native/javascript_dialog_runner_win.cc",
|
||||||
"libcef/browser/native/javascript_dialog_runner_win.h",
|
"libcef/browser/native/javascript_dialog_runner_win.h",
|
||||||
"libcef/browser/native/menu_2.cc",
|
"libcef/browser/native/menu_2.cc",
|
||||||
@ -1092,8 +1089,6 @@ static_library("libcef_static") {
|
|||||||
sources += includes_mac + [
|
sources += includes_mac + [
|
||||||
"libcef/browser/native/browser_platform_delegate_native_mac.h",
|
"libcef/browser/native/browser_platform_delegate_native_mac.h",
|
||||||
"libcef/browser/native/browser_platform_delegate_native_mac.mm",
|
"libcef/browser/native/browser_platform_delegate_native_mac.mm",
|
||||||
"libcef/browser/native/file_dialog_runner_mac.h",
|
|
||||||
"libcef/browser/native/file_dialog_runner_mac.mm",
|
|
||||||
"libcef/browser/native/javascript_dialog_runner_mac.h",
|
"libcef/browser/native/javascript_dialog_runner_mac.h",
|
||||||
"libcef/browser/native/javascript_dialog_runner_mac.mm",
|
"libcef/browser/native/javascript_dialog_runner_mac.mm",
|
||||||
"libcef/browser/native/menu_runner_mac.h",
|
"libcef/browser/native/menu_runner_mac.h",
|
||||||
|
@ -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=b80e84c0039ab45d5c4562d64b67a84766c0dab3$
|
// $hash=b1c1e44e6d3842064ef6e5b9823173f7ec1fcccc$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
|
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
|
||||||
@ -205,15 +205,12 @@ typedef struct _cef_run_file_dialog_callback_t {
|
|||||||
cef_base_ref_counted_t base;
|
cef_base_ref_counted_t base;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Called asynchronously after the file dialog is dismissed.
|
// Called asynchronously after the file dialog is dismissed. |file_paths| will
|
||||||
// |selected_accept_filter| is the 0-based index of the value selected from
|
// be a single value or a list of values depending on the dialog mode. If the
|
||||||
// the accept filters array passed to cef_browser_host_t::RunFileDialog.
|
// selection was cancelled |file_paths| will be NULL.
|
||||||
// |file_paths| will be a single value or a list of values depending on the
|
|
||||||
// dialog mode. If the selection was cancelled |file_paths| will be NULL.
|
|
||||||
///
|
///
|
||||||
void(CEF_CALLBACK* on_file_dialog_dismissed)(
|
void(CEF_CALLBACK* on_file_dialog_dismissed)(
|
||||||
struct _cef_run_file_dialog_callback_t* self,
|
struct _cef_run_file_dialog_callback_t* self,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_string_list_t file_paths);
|
cef_string_list_t file_paths);
|
||||||
} cef_run_file_dialog_callback_t;
|
} cef_run_file_dialog_callback_t;
|
||||||
|
|
||||||
@ -391,11 +388,10 @@ typedef struct _cef_browser_host_t {
|
|||||||
// selectable file types and may any combination of (a) valid lower-cased MIME
|
// selectable file types and may any combination of (a) valid lower-cased MIME
|
||||||
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
||||||
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
||||||
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
|
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg"). |callback| will be
|
||||||
// |selected_accept_filter| is the 0-based index of the filter that will be
|
// executed after the dialog is dismissed or immediately if another dialog is
|
||||||
// selected by default. |callback| will be executed after the dialog is
|
// already pending. The dialog will be initiated asynchronously on the UI
|
||||||
// dismissed or immediately if another dialog is already pending. The dialog
|
// thread.
|
||||||
// will be initiated asynchronously on the UI thread.
|
|
||||||
///
|
///
|
||||||
void(CEF_CALLBACK* run_file_dialog)(
|
void(CEF_CALLBACK* run_file_dialog)(
|
||||||
struct _cef_browser_host_t* self,
|
struct _cef_browser_host_t* self,
|
||||||
@ -403,7 +399,6 @@ typedef struct _cef_browser_host_t {
|
|||||||
const cef_string_t* title,
|
const cef_string_t* title,
|
||||||
const cef_string_t* default_file_path,
|
const cef_string_t* default_file_path,
|
||||||
cef_string_list_t accept_filters,
|
cef_string_list_t accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
struct _cef_run_file_dialog_callback_t* callback);
|
struct _cef_run_file_dialog_callback_t* callback);
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -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=0f56154217707d141912dc8a298279df8df04311$
|
// $hash=dc579beb1f25f9bbdb72afb4b5b381e129f84e31$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_
|
#ifndef CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_
|
||||||
@ -57,14 +57,11 @@ typedef struct _cef_file_dialog_callback_t {
|
|||||||
cef_base_ref_counted_t base;
|
cef_base_ref_counted_t base;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Continue the file selection. |selected_accept_filter| should be the 0-based
|
// Continue the file selection. |file_paths| should be a single value or a
|
||||||
// index of the value selected from the accept filters array passed to
|
// list of values depending on the dialog mode. An NULL |file_paths| value is
|
||||||
// cef_dialog_handler_t::OnFileDialog. |file_paths| should be a single value
|
// treated the same as calling cancel().
|
||||||
// or a list of values depending on the dialog mode. An NULL |file_paths|
|
|
||||||
// value is treated the same as calling cancel().
|
|
||||||
///
|
///
|
||||||
void(CEF_CALLBACK* cont)(struct _cef_file_dialog_callback_t* self,
|
void(CEF_CALLBACK* cont)(struct _cef_file_dialog_callback_t* self,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_string_list_t file_paths);
|
cef_string_list_t file_paths);
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -93,10 +90,9 @@ typedef struct _cef_dialog_handler_t {
|
|||||||
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
|
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
|
||||||
// individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
// individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
||||||
// description and file extension delimited using "|" and ";" (e.g. "Image
|
// description and file extension delimited using "|" and ";" (e.g. "Image
|
||||||
// Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based index of
|
// Types|.png;.gif;.jpg"). To display a custom dialog return true (1) and
|
||||||
// the filter that should be selected by default. To display a custom dialog
|
// execute |callback| either inline or at a later time. To display the default
|
||||||
// return true (1) and execute |callback| either inline or at a later time. To
|
// dialog return false (0).
|
||||||
// display the default dialog return false (0).
|
|
||||||
///
|
///
|
||||||
int(CEF_CALLBACK* on_file_dialog)(
|
int(CEF_CALLBACK* on_file_dialog)(
|
||||||
struct _cef_dialog_handler_t* self,
|
struct _cef_dialog_handler_t* self,
|
||||||
@ -105,7 +101,6 @@ typedef struct _cef_dialog_handler_t {
|
|||||||
const cef_string_t* title,
|
const cef_string_t* title,
|
||||||
const cef_string_t* default_file_path,
|
const cef_string_t* default_file_path,
|
||||||
cef_string_list_t accept_filters,
|
cef_string_list_t accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
struct _cef_file_dialog_callback_t* callback);
|
struct _cef_file_dialog_callback_t* callback);
|
||||||
} cef_dialog_handler_t;
|
} cef_dialog_handler_t;
|
||||||
|
|
||||||
|
@ -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 "1d7470ed03e8ddca6998284bef50694f5bad036c"
|
#define CEF_API_HASH_UNIVERSAL "02da3a1d216f7e3d3dcb54658d939e3d4ebf1aa0"
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#define CEF_API_HASH_PLATFORM "1c2e8c364d8dead07b5601bcac5c51392eb0821d"
|
#define CEF_API_HASH_PLATFORM "ab8b744ba6e0275c87e5640af47571692957a7b4"
|
||||||
#elif defined(OS_MAC)
|
#elif defined(OS_MAC)
|
||||||
#define CEF_API_HASH_PLATFORM "934c730bb8b18a6b987612e5e99b28173f189c72"
|
#define CEF_API_HASH_PLATFORM "77ae587ff6423e3f26dcc950ef5a894e341ddf1c"
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
#define CEF_API_HASH_PLATFORM "f45d62cfe6b26112a91404c0ff1332e3ff153b8b"
|
#define CEF_API_HASH_PLATFORM "1d805fef4907c18098039d89896ab8fec3d5e70a"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -206,14 +206,11 @@ class CefRunFileDialogCallback : public virtual CefBaseRefCounted {
|
|||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
// Called asynchronously after the file dialog is dismissed.
|
// Called asynchronously after the file dialog is dismissed.
|
||||||
// |selected_accept_filter| is the 0-based index of the value selected from
|
|
||||||
// the accept filters array passed to CefBrowserHost::RunFileDialog.
|
|
||||||
// |file_paths| will be a single value or a list of values depending on the
|
// |file_paths| will be a single value or a list of values depending on the
|
||||||
// dialog mode. If the selection was cancelled |file_paths| will be empty.
|
// dialog mode. If the selection was cancelled |file_paths| will be empty.
|
||||||
///
|
///
|
||||||
/*--cef(index_param=selected_accept_filter,optional_param=file_paths)--*/
|
/*--cef(optional_param=file_paths)--*/
|
||||||
virtual void OnFileDialogDismissed(
|
virtual void OnFileDialogDismissed(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) = 0;
|
const std::vector<CefString>& file_paths) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -421,19 +418,17 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
|
|||||||
// selectable file types and may any combination of (a) valid lower-cased MIME
|
// selectable file types and may any combination of (a) valid lower-cased MIME
|
||||||
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
||||||
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
||||||
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
|
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg"). |callback| will be
|
||||||
// |selected_accept_filter| is the 0-based index of the filter that will be
|
// executed after the dialog is dismissed or immediately if another dialog is
|
||||||
// selected by default. |callback| will be executed after the dialog is
|
// already pending. The dialog will be initiated asynchronously on the UI
|
||||||
// dismissed or immediately if another dialog is already pending. The dialog
|
// thread.
|
||||||
// will be initiated asynchronously on the UI thread.
|
|
||||||
///
|
///
|
||||||
/*--cef(optional_param=title,optional_param=default_file_path,
|
/*--cef(optional_param=title,optional_param=default_file_path,
|
||||||
optional_param=accept_filters,index_param=selected_accept_filter)--*/
|
optional_param=accept_filters)--*/
|
||||||
virtual void RunFileDialog(FileDialogMode mode,
|
virtual void RunFileDialog(FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) = 0;
|
CefRefPtr<CefRunFileDialogCallback> callback) = 0;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -48,16 +48,12 @@
|
|||||||
class CefFileDialogCallback : public virtual CefBaseRefCounted {
|
class CefFileDialogCallback : public virtual CefBaseRefCounted {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
// Continue the file selection. |selected_accept_filter| should be the 0-based
|
// Continue the file selection. |file_paths| should be a single value or a
|
||||||
// index of the value selected from the accept filters array passed to
|
|
||||||
// CefDialogHandler::OnFileDialog. |file_paths| should be a single value or a
|
|
||||||
// list of values depending on the dialog mode. An empty |file_paths| value is
|
// list of values depending on the dialog mode. An empty |file_paths| value is
|
||||||
// treated the same as calling Cancel().
|
// treated the same as calling Cancel().
|
||||||
///
|
///
|
||||||
/*--cef(capi_name=cont,index_param=selected_accept_filter,
|
/*--cef(capi_name=cont,optional_param=file_paths)--*/
|
||||||
optional_param=file_paths)--*/
|
virtual void Continue(const std::vector<CefString>& file_paths) = 0;
|
||||||
virtual void Continue(int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) = 0;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
// Cancel the file selection.
|
// Cancel the file selection.
|
||||||
@ -85,19 +81,17 @@ class CefDialogHandler : public virtual CefBaseRefCounted {
|
|||||||
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"),
|
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"),
|
||||||
// (b) individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
// (b) individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
||||||
// description and file extension delimited using "|" and ";" (e.g.
|
// description and file extension delimited using "|" and ";" (e.g.
|
||||||
// "Image Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based
|
// "Image Types|.png;.gif;.jpg"). To display a custom dialog return true and
|
||||||
// index of the filter that should be selected by default. To display a custom
|
// execute |callback| either inline or at a later time. To display the default
|
||||||
// dialog return true and execute |callback| either inline or at a later time.
|
// dialog return false.
|
||||||
// To display the default dialog return false.
|
|
||||||
///
|
///
|
||||||
/*--cef(optional_param=title,optional_param=default_file_path,
|
/*--cef(optional_param=title,optional_param=default_file_path,
|
||||||
optional_param=accept_filters,index_param=selected_accept_filter)--*/
|
optional_param=accept_filters)--*/
|
||||||
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2237,26 +2237,6 @@ typedef enum {
|
|||||||
// already exists.
|
// already exists.
|
||||||
///
|
///
|
||||||
FILE_DIALOG_SAVE,
|
FILE_DIALOG_SAVE,
|
||||||
|
|
||||||
///
|
|
||||||
// General mask defining the bits used for the type values.
|
|
||||||
///
|
|
||||||
FILE_DIALOG_TYPE_MASK = 0xFF,
|
|
||||||
|
|
||||||
// Qualifiers.
|
|
||||||
// Any of the type values above can be augmented by one or more qualifiers.
|
|
||||||
// These qualifiers further define the dialog behavior.
|
|
||||||
|
|
||||||
///
|
|
||||||
// Prompt to overwrite if the user selects an existing file with the Save
|
|
||||||
// dialog.
|
|
||||||
///
|
|
||||||
FILE_DIALOG_OVERWRITEPROMPT_FLAG = 0x01000000,
|
|
||||||
|
|
||||||
///
|
|
||||||
// Do not display read-only files.
|
|
||||||
///
|
|
||||||
FILE_DIALOG_HIDEREADONLY_FLAG = 0x02000000,
|
|
||||||
} cef_file_dialog_mode_t;
|
} cef_file_dialog_mode_t;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/callback_helpers.h"
|
#include "base/callback_helpers.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
#include "chrome/browser/file_select_helper.h"
|
||||||
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
|
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
|
||||||
#include "content/browser/gpu/compositor_util.h"
|
#include "content/browser/gpu/compositor_util.h"
|
||||||
#include "content/public/browser/desktop_media_id.h"
|
#include "content/public/browser/desktop_media_id.h"
|
||||||
@ -348,27 +349,6 @@ void AlloyBrowserHostImpl::SetZoomLevel(double zoomLevel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::RunFileDialog(
|
|
||||||
FileDialogMode mode,
|
|
||||||
const CefString& title,
|
|
||||||
const CefString& default_file_path,
|
|
||||||
const std::vector<CefString>& accept_filters,
|
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::BindOnce(&AlloyBrowserHostImpl::RunFileDialog, this,
|
|
||||||
mode, title, default_file_path, accept_filters,
|
|
||||||
selected_accept_filter, callback));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnsureFileDialogManager();
|
|
||||||
file_dialog_manager_->RunFileDialog(mode, title, default_file_path,
|
|
||||||
accept_filters, selected_accept_filter,
|
|
||||||
callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::Print() {
|
void AlloyBrowserHostImpl::Print() {
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::Print, this));
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::Print, this));
|
||||||
@ -666,8 +646,6 @@ void AlloyBrowserHostImpl::DestroyBrowser() {
|
|||||||
OnBeforeClose();
|
OnBeforeClose();
|
||||||
|
|
||||||
// Destroy any platform constructs first.
|
// Destroy any platform constructs first.
|
||||||
if (file_dialog_manager_.get())
|
|
||||||
file_dialog_manager_->Destroy();
|
|
||||||
if (javascript_dialog_manager_.get())
|
if (javascript_dialog_manager_.get())
|
||||||
javascript_dialog_manager_->Destroy();
|
javascript_dialog_manager_->Destroy();
|
||||||
if (menu_manager_.get())
|
if (menu_manager_.get())
|
||||||
@ -750,13 +728,6 @@ void AlloyBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
|
|||||||
platform_delegate_->SetFocus(true);
|
platform_delegate_->SetFocus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::RunFileChooser(
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback) {
|
|
||||||
EnsureFileDialogManager();
|
|
||||||
file_dialog_manager_->RunFileChooser(params, std::move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::EnterFullscreenModeForTab(
|
void AlloyBrowserHostImpl::EnterFullscreenModeForTab(
|
||||||
content::RenderFrameHost* requesting_frame,
|
content::RenderFrameHost* requesting_frame,
|
||||||
const blink::mojom::FullscreenOptions& options) {
|
const blink::mojom::FullscreenOptions& options) {
|
||||||
@ -1278,8 +1249,9 @@ void AlloyBrowserHostImpl::RunFileChooser(
|
|||||||
content::RenderFrameHost* render_frame_host,
|
content::RenderFrameHost* render_frame_host,
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
scoped_refptr<content::FileSelectListener> listener,
|
||||||
const blink::mojom::FileChooserParams& params) {
|
const blink::mojom::FileChooserParams& params) {
|
||||||
EnsureFileDialogManager();
|
// This will eventually call into CefFileDialogManager.
|
||||||
file_dialog_manager_->RunFileChooser(listener, params);
|
FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
|
||||||
|
params);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AlloyBrowserHostImpl::HandleContextMenu(
|
bool AlloyBrowserHostImpl::HandleContextMenu(
|
||||||
@ -1575,11 +1547,3 @@ void AlloyBrowserHostImpl::UpdateDragCursor(
|
|||||||
if (platform_delegate_)
|
if (platform_delegate_)
|
||||||
platform_delegate_->UpdateDragCursor(operation);
|
platform_delegate_->UpdateDragCursor(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::EnsureFileDialogManager() {
|
|
||||||
CEF_REQUIRE_UIT();
|
|
||||||
if (!file_dialog_manager_.get() && platform_delegate_) {
|
|
||||||
file_dialog_manager_.reset(new CefFileDialogManager(
|
|
||||||
this, platform_delegate_->CreateFileDialogRunner()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "include/cef_frame.h"
|
#include "include/cef_frame.h"
|
||||||
#include "libcef/browser/browser_host_base.h"
|
#include "libcef/browser/browser_host_base.h"
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
#include "libcef/browser/file_dialog_manager.h"
|
|
||||||
#include "libcef/browser/frame_host_impl.h"
|
#include "libcef/browser/frame_host_impl.h"
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
#include "libcef/browser/javascript_dialog_manager.h"
|
||||||
#include "libcef/browser/menu_manager.h"
|
#include "libcef/browser/menu_manager.h"
|
||||||
@ -83,12 +82,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
CefWindowHandle GetOpenerWindowHandle() override;
|
CefWindowHandle GetOpenerWindowHandle() override;
|
||||||
double GetZoomLevel() override;
|
double GetZoomLevel() override;
|
||||||
void SetZoomLevel(double zoomLevel) override;
|
void SetZoomLevel(double zoomLevel) override;
|
||||||
void RunFileDialog(FileDialogMode mode,
|
|
||||||
const CefString& title,
|
|
||||||
const CefString& default_file_path,
|
|
||||||
const std::vector<CefString>& accept_filters,
|
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
|
||||||
void Print() override;
|
void Print() override;
|
||||||
void PrintToPDF(const CefString& path,
|
void PrintToPDF(const CefString& path,
|
||||||
const CefPdfPrintSettings& settings,
|
const CefPdfPrintSettings& settings,
|
||||||
@ -178,12 +171,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
|
|
||||||
void OnSetFocus(cef_focus_source_t source) override;
|
void OnSetFocus(cef_focus_source_t source) override;
|
||||||
|
|
||||||
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
|
||||||
// be pending at any given time. |callback| will be executed asynchronously
|
|
||||||
// after the dialog is dismissed or if another dialog is already pending.
|
|
||||||
void RunFileChooser(const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback);
|
|
||||||
|
|
||||||
bool HandleContextMenu(content::WebContents* web_contents,
|
bool HandleContextMenu(content::WebContents* web_contents,
|
||||||
const content::ContextMenuParams& params);
|
const content::ContextMenuParams& params);
|
||||||
|
|
||||||
@ -329,9 +316,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
// Give the platform delegate an opportunity to create the host window.
|
// Give the platform delegate an opportunity to create the host window.
|
||||||
bool CreateHostWindow();
|
bool CreateHostWindow();
|
||||||
|
|
||||||
// Create the CefFileDialogManager if it doesn't already exist.
|
|
||||||
void EnsureFileDialogManager();
|
|
||||||
|
|
||||||
void StartAudioCapturer();
|
void StartAudioCapturer();
|
||||||
void OnRecentlyAudibleTimerFired();
|
void OnRecentlyAudibleTimerFired();
|
||||||
|
|
||||||
@ -349,9 +333,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
// on the UI thread.
|
// on the UI thread.
|
||||||
bool window_destroyed_ = false;
|
bool window_destroyed_ = false;
|
||||||
|
|
||||||
// Used for creating and managing file dialogs.
|
|
||||||
std::unique_ptr<CefFileDialogManager> file_dialog_manager_;
|
|
||||||
|
|
||||||
// Used for creating and managing JavaScript dialogs.
|
// Used for creating and managing JavaScript dialogs.
|
||||||
std::unique_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
|
std::unique_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/devtools/devtools_manager_delegate.h"
|
#include "libcef/browser/devtools/devtools_manager_delegate.h"
|
||||||
#include "libcef/browser/extensions/extension_system_factory.h"
|
#include "libcef/browser/extensions/extension_system_factory.h"
|
||||||
|
#include "libcef/browser/file_dialog_runner.h"
|
||||||
#include "libcef/browser/net/chrome_scheme_handler.h"
|
#include "libcef/browser/net/chrome_scheme_handler.h"
|
||||||
#include "libcef/browser/printing/constrained_window_views_client.h"
|
#include "libcef/browser/printing/constrained_window_views_client.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
@ -75,11 +76,23 @@
|
|||||||
|
|
||||||
#if BUILDFLAG(IS_LINUX)
|
#if BUILDFLAG(IS_LINUX)
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
|
#include "chrome/browser/themes/theme_service_aura_linux.h"
|
||||||
|
#include "chrome/browser/ui/views/theme_profile_key.h"
|
||||||
#include "chrome/common/chrome_paths.h"
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "chrome/grit/chromium_strings.h"
|
#include "chrome/grit/chromium_strings.h"
|
||||||
#include "components/os_crypt/key_storage_config_linux.h"
|
#include "components/os_crypt/key_storage_config_linux.h"
|
||||||
#include "libcef/browser/printing/print_dialog_linux.h"
|
#include "libcef/browser/printing/print_dialog_linux.h"
|
||||||
|
#include "ui/base/cursor/cursor_factory.h"
|
||||||
|
#include "ui/base/ime/input_method.h"
|
||||||
|
#include "ui/base/ime/linux/fake_input_method_context_factory.h"
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
|
#include "ui/base/linux/linux_ui_delegate.h"
|
||||||
|
#include "ui/ozone/public/ozone_platform.h"
|
||||||
|
#include "ui/views/linux_ui/linux_ui.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_GTK)
|
||||||
|
#include "ui/gtk/gtk_ui_factory.h"
|
||||||
|
#endif
|
||||||
#endif // BUILDFLAG(IS_LINUX)
|
#endif // BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
|
#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
|
||||||
@ -90,6 +103,75 @@
|
|||||||
#include "chrome/browser/component_updater/widevine_cdm_component_installer.h"
|
#include "chrome/browser/component_updater/widevine_cdm_component_installer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
|
std::unique_ptr<views::LinuxUI> BuildLinuxUI() {
|
||||||
|
// We can't use GtkUi in combination with multi-threaded-message-loop because
|
||||||
|
// Chromium's GTK implementation doesn't use GDK threads.
|
||||||
|
if (!!CefContext::Get()->settings().multi_threaded_message_loop)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// If the ozone backend hasn't provided a LinuxUiDelegate, don't try to create
|
||||||
|
// a LinuxUi instance as this may result in a crash in toolkit initialization.
|
||||||
|
if (!ui::LinuxUiDelegate::GetInstance())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// GtkUi is the only LinuxUI implementation for now.
|
||||||
|
#if BUILDFLAG(USE_GTK)
|
||||||
|
return BuildGtkUi();
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on chrome_browser_main_extra_parts_views_linux.cc
|
||||||
|
void ToolkitInitializedLinux() {
|
||||||
|
if (auto linux_ui = BuildLinuxUI()) {
|
||||||
|
linux_ui->SetUseSystemThemeCallback(
|
||||||
|
base::BindRepeating([](aura::Window* window) {
|
||||||
|
if (!window)
|
||||||
|
return true;
|
||||||
|
return ThemeServiceAuraLinux::ShouldUseSystemThemeForProfile(
|
||||||
|
GetThemeProfileForWindow(window));
|
||||||
|
}));
|
||||||
|
|
||||||
|
linux_ui->Initialize();
|
||||||
|
views::LinuxUI::SetInstance(std::move(linux_ui));
|
||||||
|
|
||||||
|
// Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager
|
||||||
|
// implementation). Start observing them once it's initialized.
|
||||||
|
ui::CursorFactory::GetInstance()->ObserveThemeChanges();
|
||||||
|
} else {
|
||||||
|
// In case if GTK is not used, input method factory won't be set for X11 and
|
||||||
|
// Ozone/X11. Set a fake one instead to avoid crashing browser later.
|
||||||
|
DCHECK(!ui::LinuxInputMethodContextFactory::instance());
|
||||||
|
// Try to create input method through Ozone so that the backend has a chance
|
||||||
|
// to set factory by itself.
|
||||||
|
ui::OzonePlatform::GetInstance()->CreateInputMethod(
|
||||||
|
nullptr, gfx::kNullAcceleratedWidget);
|
||||||
|
}
|
||||||
|
// If factory is not set, set a fake instance.
|
||||||
|
if (!ui::LinuxInputMethodContextFactory::instance()) {
|
||||||
|
ui::LinuxInputMethodContextFactory::SetInstance(
|
||||||
|
new ui::FakeInputMethodContextFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto create_print_dialog_func =
|
||||||
|
printing::PrintingContextLinux::SetCreatePrintDialogFunction(
|
||||||
|
&CefPrintDialogLinux::CreatePrintDialog);
|
||||||
|
auto pdf_paper_size_func =
|
||||||
|
printing::PrintingContextLinux::SetPdfPaperSizeFunction(
|
||||||
|
&CefPrintDialogLinux::GetPdfPaperSize);
|
||||||
|
CefPrintDialogLinux::SetDefaultPrintingContextFuncs(create_print_dialog_func,
|
||||||
|
pdf_paper_size_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AlloyBrowserMainParts::AlloyBrowserMainParts(
|
AlloyBrowserMainParts::AlloyBrowserMainParts(
|
||||||
content::MainFunctionParams parameters)
|
content::MainFunctionParams parameters)
|
||||||
: BrowserMainParts(), parameters_(std::move(parameters)) {}
|
: BrowserMainParts(), parameters_(std::move(parameters)) {}
|
||||||
@ -98,16 +180,6 @@ AlloyBrowserMainParts::~AlloyBrowserMainParts() {
|
|||||||
constrained_window::SetConstrainedWindowViewsClient(nullptr);
|
constrained_window::SetConstrainedWindowViewsClient(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AlloyBrowserMainParts::PreEarlyInitialization() {
|
|
||||||
#if defined(USE_AURA) && BUILDFLAG(IS_LINUX)
|
|
||||||
// TODO(linux): Consider using a real input method or
|
|
||||||
// views::LinuxUI::SetInstance.
|
|
||||||
ui::InitializeInputMethodForTesting();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return content::RESULT_CODE_NORMAL_EXIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlloyBrowserMainParts::ToolkitInitialized() {
|
void AlloyBrowserMainParts::ToolkitInitialized() {
|
||||||
SetConstrainedWindowViewsClient(CreateCefConstrainedWindowViewsClient());
|
SetConstrainedWindowViewsClient(CreateCefConstrainedWindowViewsClient());
|
||||||
#if defined(USE_AURA)
|
#if defined(USE_AURA)
|
||||||
@ -122,6 +194,10 @@ void AlloyBrowserMainParts::ToolkitInitialized() {
|
|||||||
#else
|
#else
|
||||||
views_delegate_ = std::make_unique<views::DesktopTestViewsDelegate>();
|
views_delegate_ = std::make_unique<views::DesktopTestViewsDelegate>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LINUX)
|
||||||
|
ToolkitInitializedLinux();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlloyBrowserMainParts::PreCreateMainMessageLoop() {
|
void AlloyBrowserMainParts::PreCreateMainMessageLoop() {
|
||||||
@ -148,11 +224,6 @@ void AlloyBrowserMainParts::PreCreateMainMessageLoop() {
|
|||||||
|
|
||||||
void AlloyBrowserMainParts::PostCreateMainMessageLoop() {
|
void AlloyBrowserMainParts::PostCreateMainMessageLoop() {
|
||||||
#if BUILDFLAG(IS_LINUX)
|
#if BUILDFLAG(IS_LINUX)
|
||||||
printing::PrintingContextLinux::SetCreatePrintDialogFunction(
|
|
||||||
&CefPrintDialogLinux::CreatePrintDialog);
|
|
||||||
printing::PrintingContextLinux::SetPdfPaperSizeFunction(
|
|
||||||
&CefPrintDialogLinux::GetPdfPaperSize);
|
|
||||||
|
|
||||||
const base::CommandLine* command_line =
|
const base::CommandLine* command_line =
|
||||||
base::CommandLine::ForCurrentProcess();
|
base::CommandLine::ForCurrentProcess();
|
||||||
|
|
||||||
@ -241,6 +312,7 @@ int AlloyBrowserMainParts::PreMainMessageLoopRun() {
|
|||||||
PluginFinder::GetInstance()->Init();
|
PluginFinder::GetInstance()->Init();
|
||||||
|
|
||||||
scheme::RegisterWebUIControllerFactory();
|
scheme::RegisterWebUIControllerFactory();
|
||||||
|
file_dialog_runner::RegisterFactory();
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM) || \
|
#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM) || \
|
||||||
BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
|
BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
|
||||||
|
@ -42,7 +42,6 @@ class AlloyBrowserMainParts : public content::BrowserMainParts {
|
|||||||
|
|
||||||
~AlloyBrowserMainParts() override;
|
~AlloyBrowserMainParts() override;
|
||||||
|
|
||||||
int PreEarlyInitialization() override;
|
|
||||||
void ToolkitInitialized() override;
|
void ToolkitInitialized() override;
|
||||||
void PreCreateMainMessageLoop() override;
|
void PreCreateMainMessageLoop() override;
|
||||||
void PostCreateMainMessageLoop() override;
|
void PostCreateMainMessageLoop() override;
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "chrome/browser/profiles/renderer_updater_factory.h"
|
#include "chrome/browser/profiles/renderer_updater_factory.h"
|
||||||
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
||||||
#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
|
#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
|
||||||
|
#include "chrome/browser/ui/chrome_select_file_policy.h"
|
||||||
#include "chrome/common/chrome_content_client.h"
|
#include "chrome/common/chrome_content_client.h"
|
||||||
#include "chrome/common/chrome_paths.h"
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "chrome/common/chrome_switches.h"
|
#include "chrome/common/chrome_switches.h"
|
||||||
@ -576,6 +577,12 @@ void AlloyContentBrowserClient::GetAdditionalViewSourceSchemes(
|
|||||||
additional_schemes->push_back(extensions::kExtensionScheme);
|
additional_schemes->push_back(extensions::kExtensionScheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy>
|
||||||
|
AlloyContentBrowserClient::CreateSelectFilePolicy(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
return std::make_unique<ChromeSelectFilePolicy>(web_contents);
|
||||||
|
}
|
||||||
|
|
||||||
void AlloyContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
void AlloyContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||||
std::vector<std::string>* additional_allowed_schemes) {
|
std::vector<std::string>* additional_allowed_schemes) {
|
||||||
ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||||
|
@ -58,6 +58,8 @@ class AlloyContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
std::vector<std::string>* additional_schemes) override;
|
std::vector<std::string>* additional_schemes) override;
|
||||||
void GetAdditionalViewSourceSchemes(
|
void GetAdditionalViewSourceSchemes(
|
||||||
std::vector<std::string>* additional_schemes) override;
|
std::vector<std::string>* additional_schemes) override;
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> CreateSelectFilePolicy(
|
||||||
|
content::WebContents* web_contents) override;
|
||||||
void GetAdditionalAllowedSchemesForFileSystem(
|
void GetAdditionalAllowedSchemesForFileSystem(
|
||||||
std::vector<std::string>* additional_allowed_schemes) override;
|
std::vector<std::string>* additional_allowed_schemes) override;
|
||||||
bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
|
bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2021 The Chromium Embedded Framework 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_dialog_util.h"
|
|
||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
|
||||||
#include "libcef/browser/extensions/browser_extensions_util.h"
|
|
||||||
#include "libcef/browser/file_dialog_runner.h"
|
|
||||||
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
|
||||||
|
|
||||||
namespace alloy {
|
|
||||||
|
|
||||||
void RunFileChooser(content::WebContents* web_contents,
|
|
||||||
const blink::mojom::FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) {
|
|
||||||
CefRefPtr<AlloyBrowserHostImpl> browser = static_cast<AlloyBrowserHostImpl*>(
|
|
||||||
extensions::GetOwnerBrowserForHost(web_contents->GetRenderViewHost(),
|
|
||||||
nullptr)
|
|
||||||
.get());
|
|
||||||
if (!browser) {
|
|
||||||
LOG(ERROR) << "Failed to identify browser; canceling file dialog";
|
|
||||||
std::move(callback).Run(-1, {});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefFileDialogRunner::FileChooserParams cef_params;
|
|
||||||
cef_params.mode = params.mode;
|
|
||||||
cef_params.default_file_name = params.default_file_name;
|
|
||||||
cef_params.accept_types = params.accept_types;
|
|
||||||
|
|
||||||
browser->RunFileChooser(cef_params, std::move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on net/base/filename_util_internal.cc FilePathToString16().
|
|
||||||
std::u16string FilePathTypeToString16(const base::FilePath::StringType& str) {
|
|
||||||
std::u16string result;
|
|
||||||
#if BUILDFLAG(IS_WIN)
|
|
||||||
result.assign(str.begin(), str.end());
|
|
||||||
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
|
|
||||||
if (!str.empty()) {
|
|
||||||
base::UTF8ToUTF16(str.c_str(), str.size(), &result);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace alloy
|
|
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2021 The Chromium Embedded Framework 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_DIALOG_UTIL_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DIALOG_UTIL_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "base/callback.h"
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
|
||||||
|
|
||||||
namespace content {
|
|
||||||
class WebContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace alloy {
|
|
||||||
|
|
||||||
// The argument vector will be empty if the dialog was canceled.
|
|
||||||
using RunFileChooserCallback =
|
|
||||||
base::OnceCallback<void(int /*selected_accept_filter*/,
|
|
||||||
const std::vector<base::FilePath>& /*file_paths*/)>;
|
|
||||||
|
|
||||||
// Display the file chooser dialog. Execute |callback| on completion.
|
|
||||||
// Called from patched chrome/ files.
|
|
||||||
void RunFileChooser(content::WebContents* web_contents,
|
|
||||||
const blink::mojom::FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback);
|
|
||||||
|
|
||||||
std::u16string FilePathTypeToString16(const base::FilePath::StringType& str);
|
|
||||||
|
|
||||||
} // namespace alloy
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DIALOG_UTIL_H_
|
|
@ -129,13 +129,12 @@ base::Time ChromeProfileAlloy::GetStartTime() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
base::FilePath ChromeProfileAlloy::last_selected_directory() {
|
base::FilePath ChromeProfileAlloy::last_selected_directory() {
|
||||||
NOTREACHED();
|
return last_selected_directory_;
|
||||||
return base::FilePath();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChromeProfileAlloy::set_last_selected_directory(
|
void ChromeProfileAlloy::set_last_selected_directory(
|
||||||
const base::FilePath& path) {
|
const base::FilePath& path) {
|
||||||
NOTREACHED();
|
last_selected_directory_ = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
GURL ChromeProfileAlloy::GetHomePage() {
|
GURL ChromeProfileAlloy::GetHomePage() {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#ifndef CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
#ifndef CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
||||||
#define CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
#define CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
#include "chrome/browser/profiles/profile.h"
|
#include "chrome/browser/profiles/profile.h"
|
||||||
|
|
||||||
// This file provides a stub implementation of Chrome's Profile object for use
|
// This file provides a stub implementation of Chrome's Profile object for use
|
||||||
@ -54,6 +55,7 @@ class ChromeProfileAlloy : public Profile {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<variations::VariationsClient> variations_client_;
|
std::unique_ptr<variations::VariationsClient> variations_client_;
|
||||||
|
base::FilePath last_selected_directory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
#endif // CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
|
||||||
|
@ -20,11 +20,14 @@
|
|||||||
#include "chrome/browser/spellchecker/spellcheck_service.h"
|
#include "chrome/browser/spellchecker/spellcheck_service.h"
|
||||||
#include "components/favicon/core/favicon_url.h"
|
#include "components/favicon/core/favicon_url.h"
|
||||||
#include "components/spellcheck/common/spellcheck_features.h"
|
#include "components/spellcheck/common/spellcheck_features.h"
|
||||||
|
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/download_manager.h"
|
#include "content/public/browser/download_manager.h"
|
||||||
#include "content/public/browser/download_request_utils.h"
|
#include "content/public/browser/download_request_utils.h"
|
||||||
|
#include "content/public/browser/file_select_listener.h"
|
||||||
#include "content/public/browser/navigation_entry.h"
|
#include "content/public/browser/navigation_entry.h"
|
||||||
#include "ui/gfx/image/image_skia.h"
|
#include "ui/gfx/image/image_skia.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_policy.h"
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
#include "components/spellcheck/browser/spellcheck_platform.h"
|
#include "components/spellcheck/browser/spellcheck_platform.h"
|
||||||
@ -208,6 +211,31 @@ void CefBrowserHostBase::SetFocusInternal(bool focus) {
|
|||||||
platform_delegate_->SetFocus(false);
|
platform_delegate_->SetFocus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefBrowserHostBase::RunFileDialog(
|
||||||
|
FileDialogMode mode,
|
||||||
|
const CefString& title,
|
||||||
|
const CefString& default_file_path,
|
||||||
|
const std::vector<CefString>& accept_filters,
|
||||||
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
|
DCHECK(callback);
|
||||||
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::RunFileDialog,
|
||||||
|
this, mode, title, default_file_path,
|
||||||
|
accept_filters, callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!callback || !EnsureFileDialogManager()) {
|
||||||
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
||||||
|
if (callback)
|
||||||
|
callback->OnFileDialogDismissed({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_dialog_manager_->RunFileDialog(mode, title, default_file_path,
|
||||||
|
accept_filters, callback);
|
||||||
|
}
|
||||||
|
|
||||||
void CefBrowserHostBase::StartDownload(const CefString& url) {
|
void CefBrowserHostBase::StartDownload(const CefString& url) {
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
CEF_POST_TASK(
|
CEF_POST_TASK(
|
||||||
@ -805,6 +833,45 @@ void CefBrowserHostBase::ViewText(const std::string& text) {
|
|||||||
platform_delegate_->ViewText(text);
|
platform_delegate_->ViewText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefBrowserHostBase::RunFileChooserForBrowser(
|
||||||
|
const blink::mojom::FileChooserParams& params,
|
||||||
|
CefFileDialogManager::RunFileChooserCallback callback) {
|
||||||
|
if (!EnsureFileDialogManager()) {
|
||||||
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
||||||
|
std::move(callback).Run({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file_dialog_manager_->RunFileChooser(params, std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserHostBase::RunSelectFile(
|
||||||
|
ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy,
|
||||||
|
ui::SelectFileDialog::Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const ui::SelectFileDialog::FileTypeInfo* file_types,
|
||||||
|
int file_type_index,
|
||||||
|
const base::FilePath::StringType& default_extension,
|
||||||
|
gfx::NativeWindow owning_window,
|
||||||
|
void* params) {
|
||||||
|
if (!EnsureFileDialogManager()) {
|
||||||
|
LOG(ERROR) << "File dialog canceled due to invalid state.";
|
||||||
|
listener->FileSelectionCanceled(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file_dialog_manager_->RunSelectFile(listener, std::move(policy), type, title,
|
||||||
|
default_path, file_types, file_type_index,
|
||||||
|
default_extension, owning_window, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserHostBase::SelectFileListenerDestroyed(
|
||||||
|
ui::SelectFileDialog::Listener* listener) {
|
||||||
|
if (file_dialog_manager_) {
|
||||||
|
file_dialog_manager_->SelectFileListenerDestroyed(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CefBrowserHostBase::MaybeAllowNavigation(
|
bool CefBrowserHostBase::MaybeAllowNavigation(
|
||||||
content::RenderFrameHost* opener,
|
content::RenderFrameHost* opener,
|
||||||
bool is_guest_view,
|
bool is_guest_view,
|
||||||
@ -833,6 +900,13 @@ void CefBrowserHostBase::OnBeforeClose() {
|
|||||||
|
|
||||||
void CefBrowserHostBase::OnBrowserDestroyed() {
|
void CefBrowserHostBase::OnBrowserDestroyed() {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
|
// Destroy any platform constructs.
|
||||||
|
if (file_dialog_manager_) {
|
||||||
|
file_dialog_manager_->Destroy();
|
||||||
|
file_dialog_manager_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& observer : observers_)
|
for (auto& observer : observers_)
|
||||||
observer.OnBrowserDestroyed(this);
|
observer.OnBrowserDestroyed(this);
|
||||||
}
|
}
|
||||||
@ -878,13 +952,36 @@ CefRefPtr<CefBrowserView> CefBrowserHostBase::GetBrowserView() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::NativeWindow CefBrowserHostBase::GetTopLevelNativeWindow() const {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
// Windowless browsers always return nullptr from GetTopLevelNativeWindow().
|
||||||
|
if (!IsWindowless()) {
|
||||||
|
auto web_contents = GetWebContents();
|
||||||
|
if (web_contents) {
|
||||||
|
return web_contents->GetTopLevelNativeWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gfx::NativeWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserHostBase::IsFocused() const {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
auto web_contents = GetWebContents();
|
||||||
|
if (web_contents) {
|
||||||
|
return static_cast<content::RenderFrameHostImpl*>(
|
||||||
|
web_contents->GetMainFrame())
|
||||||
|
->IsFocused();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CefBrowserHostBase::EnsureDevToolsManager() {
|
bool CefBrowserHostBase::EnsureDevToolsManager() {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
if (!contents_delegate_->web_contents())
|
if (!contents_delegate_->web_contents())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!devtools_manager_) {
|
if (!devtools_manager_) {
|
||||||
devtools_manager_.reset(new CefDevToolsManager(this));
|
devtools_manager_ = std::make_unique<CefDevToolsManager>(this);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -904,3 +1001,14 @@ void CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread(
|
|||||||
return;
|
return;
|
||||||
devtools_manager_->InitializeRegistrationOnUIThread(registration);
|
devtools_manager_->InitializeRegistrationOnUIThread(registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefBrowserHostBase::EnsureFileDialogManager() {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
if (!contents_delegate_->web_contents())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!file_dialog_manager_) {
|
||||||
|
file_dialog_manager_ = std::make_unique<CefFileDialogManager>(this);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
#include "libcef/browser/browser_platform_delegate.h"
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
#include "libcef/browser/devtools/devtools_manager.h"
|
#include "libcef/browser/devtools/devtools_manager.h"
|
||||||
|
#include "libcef/browser/file_dialog_manager.h"
|
||||||
#include "libcef/browser/frame_host_impl.h"
|
#include "libcef/browser/frame_host_impl.h"
|
||||||
#include "libcef/browser/request_context_impl.h"
|
#include "libcef/browser/request_context_impl.h"
|
||||||
|
|
||||||
@ -156,6 +157,11 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
CefRefPtr<CefRequestContext> GetRequestContext() override;
|
CefRefPtr<CefRequestContext> GetRequestContext() override;
|
||||||
bool HasView() override;
|
bool HasView() override;
|
||||||
void SetFocus(bool focus) override;
|
void SetFocus(bool focus) override;
|
||||||
|
void RunFileDialog(FileDialogMode mode,
|
||||||
|
const CefString& title,
|
||||||
|
const CefString& default_file_path,
|
||||||
|
const std::vector<CefString>& accept_filters,
|
||||||
|
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
||||||
void StartDownload(const CefString& url) override;
|
void StartDownload(const CefString& url) override;
|
||||||
void DownloadImage(const CefString& image_url,
|
void DownloadImage(const CefString& image_url,
|
||||||
bool is_favicon,
|
bool is_favicon,
|
||||||
@ -234,6 +240,22 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
virtual void OnSetFocus(cef_focus_source_t source) = 0;
|
virtual void OnSetFocus(cef_focus_source_t source) = 0;
|
||||||
void ViewText(const std::string& text);
|
void ViewText(const std::string& text);
|
||||||
|
|
||||||
|
// Calls CefFileDialogManager methods.
|
||||||
|
void RunFileChooserForBrowser(
|
||||||
|
const blink::mojom::FileChooserParams& params,
|
||||||
|
CefFileDialogManager::RunFileChooserCallback callback);
|
||||||
|
void RunSelectFile(ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy,
|
||||||
|
ui::SelectFileDialog::Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const ui::SelectFileDialog::FileTypeInfo* file_types,
|
||||||
|
int file_type_index,
|
||||||
|
const base::FilePath::StringType& default_extension,
|
||||||
|
gfx::NativeWindow owning_window,
|
||||||
|
void* params);
|
||||||
|
void SelectFileListenerDestroyed(ui::SelectFileDialog::Listener* listener);
|
||||||
|
|
||||||
// Called from CefBrowserInfoManager::MaybeAllowNavigation.
|
// Called from CefBrowserInfoManager::MaybeAllowNavigation.
|
||||||
virtual bool MaybeAllowNavigation(content::RenderFrameHost* opener,
|
virtual bool MaybeAllowNavigation(content::RenderFrameHost* opener,
|
||||||
bool is_guest_view,
|
bool is_guest_view,
|
||||||
@ -269,13 +291,27 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the Widget owner for the browser window. Only used with windowed
|
// Returns the Widget owner for the browser window. Only used with windowed
|
||||||
// rendering.
|
// browsers.
|
||||||
views::Widget* GetWindowWidget() const;
|
views::Widget* GetWindowWidget() const;
|
||||||
|
|
||||||
// Returns the BrowserView associated with this browser. Only used with Views-
|
// Returns the BrowserView associated with this browser. Only used with Views-
|
||||||
// based browsers.
|
// based browsers.
|
||||||
CefRefPtr<CefBrowserView> GetBrowserView() const;
|
CefRefPtr<CefBrowserView> GetBrowserView() const;
|
||||||
|
|
||||||
|
// Returns the top-level native window for this browser. With windowed
|
||||||
|
// browsers this will be an aura::Window* on Aura platforms (Windows/Linux)
|
||||||
|
// and an NSWindow wrapper object from native_widget_types.h on MacOS. With
|
||||||
|
// windowless browsers this method will always return an empty value.
|
||||||
|
gfx::NativeWindow GetTopLevelNativeWindow() const;
|
||||||
|
|
||||||
|
// Returns true if this browser is currently focused. A browser is considered
|
||||||
|
// focused when the top-level RenderFrameHost is in the parent chain of the
|
||||||
|
// currently focused RFH within the frame tree. In addition, its associated
|
||||||
|
// RenderWidgetHost must also be focused. With windowed browsers only one
|
||||||
|
// browser should be focused at a time. With windowless browsers this relies
|
||||||
|
// on the client to properly configure focus state.
|
||||||
|
bool IsFocused() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool EnsureDevToolsManager();
|
bool EnsureDevToolsManager();
|
||||||
void InitializeDevToolsRegistrationOnUIThread(
|
void InitializeDevToolsRegistrationOnUIThread(
|
||||||
@ -286,6 +322,9 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
|
|
||||||
void SetFocusInternal(bool focus);
|
void SetFocusInternal(bool focus);
|
||||||
|
|
||||||
|
// Create the CefFileDialogManager if it doesn't already exist.
|
||||||
|
bool EnsureFileDialogManager();
|
||||||
|
|
||||||
// Thread-safe members.
|
// Thread-safe members.
|
||||||
CefBrowserSettings settings_;
|
CefBrowserSettings settings_;
|
||||||
CefRefPtr<CefClient> client_;
|
CefRefPtr<CefClient> client_;
|
||||||
@ -301,6 +340,9 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
// Only accessed on the UI thread.
|
// Only accessed on the UI thread.
|
||||||
base::ObserverList<Observer> observers_;
|
base::ObserverList<Observer> observers_;
|
||||||
|
|
||||||
|
// Used for creating and managing file dialogs.
|
||||||
|
std::unique_ptr<CefFileDialogManager> file_dialog_manager_;
|
||||||
|
|
||||||
// Volatile state accessed from multiple threads. All access must be protected
|
// Volatile state accessed from multiple threads. All access must be protected
|
||||||
// by |state_lock_|.
|
// by |state_lock_|.
|
||||||
base::Lock state_lock_;
|
base::Lock state_lock_;
|
||||||
|
@ -223,12 +223,6 @@ CefEventHandle CefBrowserPlatformDelegate::GetEventHandle(
|
|||||||
return kNullEventHandle;
|
return kNullEventHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegate::CreateFileDialogRunner() {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegate::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegate::CreateJavaScriptDialogRunner() {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
|
@ -63,7 +63,6 @@ class Widget;
|
|||||||
|
|
||||||
struct CefBrowserCreateParams;
|
struct CefBrowserCreateParams;
|
||||||
class CefBrowserHostBase;
|
class CefBrowserHostBase;
|
||||||
class CefFileDialogRunner;
|
|
||||||
class CefJavaScriptDialogRunner;
|
class CefJavaScriptDialogRunner;
|
||||||
class CefMenuRunner;
|
class CefMenuRunner;
|
||||||
|
|
||||||
@ -266,9 +265,6 @@ class CefBrowserPlatformDelegate {
|
|||||||
virtual CefEventHandle GetEventHandle(
|
virtual CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const;
|
const content::NativeWebKeyboardEvent& event) const;
|
||||||
|
|
||||||
// Create the platform-specific file dialog runner.
|
|
||||||
virtual std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner();
|
|
||||||
|
|
||||||
// Create the platform-specific JavaScript dialog runner.
|
// Create the platform-specific JavaScript dialog runner.
|
||||||
virtual std::unique_ptr<CefJavaScriptDialogRunner>
|
virtual std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CreateJavaScriptDialogRunner();
|
CreateJavaScriptDialogRunner();
|
||||||
|
@ -186,17 +186,6 @@ void ChromeBrowserHostImpl::SetZoomLevel(double zoomLevel) {
|
|||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChromeBrowserHostImpl::RunFileDialog(
|
|
||||||
FileDialogMode mode,
|
|
||||||
const CefString& title,
|
|
||||||
const CefString& default_file_path,
|
|
||||||
const std::vector<CefString>& accept_filters,
|
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
callback->OnFileDialogDismissed(0, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChromeBrowserHostImpl::Print() {
|
void ChromeBrowserHostImpl::Print() {
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::Print, this));
|
CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::Print, this));
|
||||||
|
@ -66,12 +66,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
|
|||||||
CefWindowHandle GetOpenerWindowHandle() override;
|
CefWindowHandle GetOpenerWindowHandle() override;
|
||||||
double GetZoomLevel() override;
|
double GetZoomLevel() override;
|
||||||
void SetZoomLevel(double zoomLevel) override;
|
void SetZoomLevel(double zoomLevel) override;
|
||||||
void RunFileDialog(FileDialogMode mode,
|
|
||||||
const CefString& title,
|
|
||||||
const CefString& default_file_path,
|
|
||||||
const std::vector<CefString>& accept_filters,
|
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
|
||||||
void Print() override;
|
void Print() override;
|
||||||
void PrintToPDF(const CefString& path,
|
void PrintToPDF(const CefString& path,
|
||||||
const CefPdfPrintSettings& settings,
|
const CefPdfPrintSettings& settings,
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "libcef/browser/chrome/chrome_context_menu_handler.h"
|
#include "libcef/browser/chrome/chrome_context_menu_handler.h"
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
|
#include "libcef/browser/file_dialog_runner.h"
|
||||||
#include "libcef/browser/net/chrome_scheme_handler.h"
|
#include "libcef/browser/net/chrome_scheme_handler.h"
|
||||||
|
|
||||||
#include "base/task/post_task.h"
|
#include "base/task/post_task.h"
|
||||||
@ -41,4 +42,5 @@ void ChromeBrowserMainExtraPartsCef::PreMainMessageLoopRun() {
|
|||||||
|
|
||||||
scheme::RegisterWebUIControllerFactory();
|
scheme::RegisterWebUIControllerFactory();
|
||||||
context_menu::RegisterMenuCreatedCallback();
|
context_menu::RegisterMenuCreatedCallback();
|
||||||
|
file_dialog_runner::RegisterFactory();
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ void CefDevToolsFileManager::Save(const std::string& url,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CefFileDialogRunner::FileChooserParams params;
|
blink::mojom::FileChooserParams params;
|
||||||
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
||||||
if (!initial_path.empty()) {
|
if (!initial_path.empty()) {
|
||||||
params.default_file_name = initial_path;
|
params.default_file_name = initial_path;
|
||||||
@ -115,7 +115,7 @@ void CefDevToolsFileManager::Save(const std::string& url,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
browser_impl_->RunFileChooser(
|
browser_impl_->RunFileChooserForBrowser(
|
||||||
params,
|
params,
|
||||||
base::BindOnce(&CefDevToolsFileManager::SaveAsDialogDismissed,
|
base::BindOnce(&CefDevToolsFileManager::SaveAsDialogDismissed,
|
||||||
weak_factory_.GetWeakPtr(), url, content,
|
weak_factory_.GetWeakPtr(), url, content,
|
||||||
@ -127,7 +127,6 @@ void CefDevToolsFileManager::SaveAsDialogDismissed(
|
|||||||
const std::string& content,
|
const std::string& content,
|
||||||
SaveCallback saveCallback,
|
SaveCallback saveCallback,
|
||||||
CancelCallback cancelCallback,
|
CancelCallback cancelCallback,
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
if (file_paths.size() == 1) {
|
if (file_paths.size() == 1) {
|
||||||
SaveAsFileSelected(url, content, std::move(saveCallback), file_paths[0]);
|
SaveAsFileSelected(url, content, std::move(saveCallback), file_paths[0]);
|
||||||
|
@ -49,7 +49,6 @@ class CefDevToolsFileManager {
|
|||||||
const std::string& content,
|
const std::string& content,
|
||||||
SaveCallback saveCallback,
|
SaveCallback saveCallback,
|
||||||
CancelCallback cancelCallback,
|
CancelCallback cancelCallback,
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
const std::vector<base::FilePath>& file_paths);
|
||||||
void SaveAsFileSelected(const std::string& url,
|
void SaveAsFileSelected(const std::string& url,
|
||||||
const std::string& content,
|
const std::string& content,
|
||||||
|
@ -136,7 +136,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
if (browser.get()) {
|
if (browser.get()) {
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
CefFileDialogRunner::FileChooserParams params;
|
blink::mojom::FileChooserParams params;
|
||||||
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
||||||
if (!suggested_path.empty()) {
|
if (!suggested_path.empty()) {
|
||||||
params.default_file_name = suggested_path;
|
params.default_file_name = suggested_path;
|
||||||
@ -146,7 +146,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
browser->RunFileChooser(
|
browser->RunFileChooserForBrowser(
|
||||||
params,
|
params,
|
||||||
base::BindOnce(
|
base::BindOnce(
|
||||||
&CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
|
&CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
|
||||||
@ -166,7 +166,6 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
|
|
||||||
static void ChooseDownloadPathCallback(
|
static void ChooseDownloadPathCallback(
|
||||||
content::DownloadTargetCallback callback,
|
content::DownloadTargetCallback callback,
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
DCHECK_LE(file_paths.size(), (size_t)1);
|
DCHECK_LE(file_paths.size(), (size_t)1);
|
||||||
|
|
||||||
|
@ -4,18 +4,14 @@
|
|||||||
|
|
||||||
#include "libcef/browser/extensions/api/file_system/cef_file_system_delegate.h"
|
#include "libcef/browser/extensions/api/file_system/cef_file_system_delegate.h"
|
||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_dialog_util.h"
|
|
||||||
|
|
||||||
#include "apps/saved_files_service.h"
|
#include "apps/saved_files_service.h"
|
||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "base/callback_forward.h"
|
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
|
#include "chrome/browser/extensions/api/file_system/file_entry_picker.h"
|
||||||
#include "chrome/grit/generated_resources.h"
|
#include "chrome/grit/generated_resources.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "extensions/common/api/file_system.h"
|
#include "extensions/common/api/file_system.h"
|
||||||
#include "extensions/common/extension.h"
|
#include "extensions/common/extension.h"
|
||||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
||||||
|
|
||||||
using blink::mojom::FileChooserParams;
|
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
namespace cef {
|
namespace cef {
|
||||||
@ -46,61 +42,17 @@ bool CefFileSystemDelegate::ShowSelectFileDialog(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<FileChooserParams::Mode> mode;
|
// The file picker will hold a reference to the ExtensionFunction
|
||||||
switch (type) {
|
// instance, preventing its destruction (and subsequent sending of the
|
||||||
case ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER:
|
// function response) until the user has selected a file or cancelled the
|
||||||
mode = FileChooserParams::Mode::kUploadFolder;
|
// picker. At that point, the picker will delete itself, which will also free
|
||||||
break;
|
// the function instance.
|
||||||
case ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE:
|
new FileEntryPicker(web_contents, default_path, *file_types, type,
|
||||||
mode = FileChooserParams::Mode::kSave;
|
std::move(files_selected_callback),
|
||||||
break;
|
std::move(file_selection_canceled_callback));
|
||||||
case ui::SelectFileDialog::Type::SELECT_OPEN_FILE:
|
|
||||||
mode = FileChooserParams::Mode::kOpen;
|
|
||||||
break;
|
|
||||||
case ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE:
|
|
||||||
mode = FileChooserParams::Mode::kOpenMultiple;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileChooserParams params;
|
|
||||||
params.mode = *mode;
|
|
||||||
params.default_file_name = default_path;
|
|
||||||
if (file_types) {
|
|
||||||
// A list of allowed extensions. For example, it might be
|
|
||||||
// { { "htm", "html" }, { "txt" } }
|
|
||||||
for (auto& vec : file_types->extensions) {
|
|
||||||
for (auto& ext : vec) {
|
|
||||||
params.accept_types.push_back(
|
|
||||||
alloy::FilePathTypeToString16(FILE_PATH_LITERAL(".") + ext));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alloy::RunFileChooser(
|
|
||||||
web_contents, params,
|
|
||||||
base::BindOnce(&CefFileSystemDelegate::FileDialogDismissed,
|
|
||||||
weak_ptr_factory_.GetWeakPtr(),
|
|
||||||
std::move(files_selected_callback),
|
|
||||||
std::move(file_selection_canceled_callback)));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefFileSystemDelegate::FileDialogDismissed(
|
|
||||||
FileSystemDelegate::FilesSelectedCallback files_selected_callback,
|
|
||||||
base::OnceClosure file_selection_canceled_callback,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
|
||||||
if (!file_paths.empty()) {
|
|
||||||
std::move(files_selected_callback).Run(file_paths);
|
|
||||||
} else {
|
|
||||||
std::move(file_selection_canceled_callback).Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefFileSystemDelegate::ConfirmSensitiveDirectoryAccess(
|
void CefFileSystemDelegate::ConfirmSensitiveDirectoryAccess(
|
||||||
bool has_write_permission,
|
bool has_write_permission,
|
||||||
const std::u16string& app_name,
|
const std::u16string& app_name,
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/memory/weak_ptr.h"
|
|
||||||
#include "extensions/browser/api/execute_code_function.h"
|
#include "extensions/browser/api/execute_code_function.h"
|
||||||
#include "extensions/browser/api/file_system/file_system_delegate.h"
|
#include "extensions/browser/api/file_system/file_system_delegate.h"
|
||||||
#include "extensions/browser/extension_function.h"
|
#include "extensions/browser/extension_function.h"
|
||||||
@ -51,15 +50,6 @@ class CefFileSystemDelegate : public FileSystemDelegate {
|
|||||||
int GetDescriptionIdForAcceptType(const std::string& accept_type) override;
|
int GetDescriptionIdForAcceptType(const std::string& accept_type) override;
|
||||||
SavedFilesServiceInterface* GetSavedFilesService(
|
SavedFilesServiceInterface* GetSavedFilesService(
|
||||||
content::BrowserContext* browser_context) override;
|
content::BrowserContext* browser_context) override;
|
||||||
|
|
||||||
private:
|
|
||||||
void FileDialogDismissed(
|
|
||||||
FileSystemDelegate::FilesSelectedCallback files_selected_callback,
|
|
||||||
base::OnceClosure file_selection_canceled_callback,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
base::WeakPtrFactory<CefFileSystemDelegate> weak_ptr_factory_{this};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cef
|
} // namespace cef
|
||||||
|
@ -102,11 +102,6 @@ CefEventHandle CefBrowserPlatformDelegateBackground::GetEventHandle(
|
|||||||
return native_delegate_->GetEventHandle(event);
|
return native_delegate_->GetEventHandle(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegateBackground::CreateFileDialogRunner() {
|
|
||||||
return native_delegate_->CreateFileDialogRunner();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegateBackground::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegateBackground::CreateJavaScriptDialogRunner() {
|
||||||
return native_delegate_->CreateJavaScriptDialogRunner();
|
return native_delegate_->CreateJavaScriptDialogRunner();
|
||||||
|
@ -40,7 +40,6 @@ class CefBrowserPlatformDelegateBackground
|
|||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const override;
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
||||||
override;
|
override;
|
||||||
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
@ -8,18 +8,22 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "include/cef_dialog_handler.h"
|
#include "include/cef_dialog_handler.h"
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
#include "libcef/browser/browser_host_base.h"
|
||||||
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
|
#include "chrome/browser/file_select_helper.h"
|
||||||
#include "content/public/browser/file_select_listener.h"
|
#include "content/public/browser/file_select_listener.h"
|
||||||
#include "content/public/browser/render_frame_host.h"
|
#include "content/public/browser/render_frame_host.h"
|
||||||
#include "net/base/directory_lister.h"
|
#include "ui/shell_dialogs/select_file_policy.h"
|
||||||
|
|
||||||
|
using blink::mojom::FileChooserParams;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
||||||
public:
|
public:
|
||||||
using CallbackType = CefFileDialogRunner::RunFileChooserCallback;
|
using CallbackType = CefFileDialogManager::RunFileChooserCallback;
|
||||||
|
|
||||||
explicit CefFileDialogCallbackImpl(CallbackType callback)
|
explicit CefFileDialogCallbackImpl(CallbackType callback)
|
||||||
: callback_(std::move(callback)) {}
|
: callback_(std::move(callback)) {}
|
||||||
@ -37,8 +41,7 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continue(int selected_accept_filter,
|
void Continue(const std::vector<CefString>& file_paths) override {
|
||||||
const std::vector<CefString>& file_paths) override {
|
|
||||||
if (CEF_CURRENTLY_ON_UIT()) {
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
if (!callback_.is_null()) {
|
if (!callback_.is_null()) {
|
||||||
std::vector<base::FilePath> vec;
|
std::vector<base::FilePath> vec;
|
||||||
@ -47,12 +50,12 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
for (; it != file_paths.end(); ++it)
|
for (; it != file_paths.end(); ++it)
|
||||||
vec.push_back(base::FilePath(*it));
|
vec.push_back(base::FilePath(*it));
|
||||||
}
|
}
|
||||||
std::move(callback_).Run(selected_accept_filter, vec);
|
std::move(callback_).Run(vec);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CEF_POST_TASK(CEF_UIT,
|
CEF_POST_TASK(CEF_UIT,
|
||||||
base::BindOnce(&CefFileDialogCallbackImpl::Continue, this,
|
base::BindOnce(&CefFileDialogCallbackImpl::Continue, this,
|
||||||
selected_accept_filter, file_paths));
|
file_paths));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +76,7 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
static void CancelNow(CallbackType callback) {
|
static void CancelNow(CallbackType callback) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
std::vector<base::FilePath> file_paths;
|
std::vector<base::FilePath> file_paths;
|
||||||
std::move(callback).Run(0, file_paths);
|
std::move(callback).Run(file_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallbackType callback_;
|
CallbackType callback_;
|
||||||
@ -82,77 +85,210 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void RunFileDialogDismissed(CefRefPtr<CefRunFileDialogCallback> callback,
|
void RunFileDialogDismissed(CefRefPtr<CefRunFileDialogCallback> callback,
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
std::vector<CefString> paths;
|
std::vector<CefString> paths;
|
||||||
if (file_paths.size() > 0) {
|
if (file_paths.size() > 0) {
|
||||||
for (size_t i = 0; i < file_paths.size(); ++i)
|
for (size_t i = 0; i < file_paths.size(); ++i)
|
||||||
paths.push_back(file_paths[i].value());
|
paths.push_back(file_paths[i].value());
|
||||||
}
|
}
|
||||||
callback->OnFileDialogDismissed(selected_accept_filter, paths);
|
callback->OnFileDialogDismissed(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UploadFolderHelper
|
// Based on net/base/filename_util_internal.cc FilePathToString16().
|
||||||
: public net::DirectoryLister::DirectoryListerDelegate {
|
std::u16string FilePathTypeToString16(const base::FilePath::StringType& str) {
|
||||||
public:
|
std::u16string result;
|
||||||
explicit UploadFolderHelper(
|
#if BUILDFLAG(IS_WIN)
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback)
|
result.assign(str.begin(), str.end());
|
||||||
: callback_(std::move(callback)) {}
|
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
|
||||||
|
if (!str.empty()) {
|
||||||
|
base::UTF8ToUTF16(str.c_str(), str.size(), &result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
UploadFolderHelper(const UploadFolderHelper&) = delete;
|
FileChooserParams SelectFileToFileChooserParams(
|
||||||
UploadFolderHelper& operator=(const UploadFolderHelper&) = delete;
|
ui::SelectFileDialog::Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const ui::SelectFileDialog::FileTypeInfo* file_types) {
|
||||||
|
FileChooserParams params;
|
||||||
|
|
||||||
~UploadFolderHelper() override {
|
absl::optional<FileChooserParams::Mode> mode;
|
||||||
if (!callback_.is_null()) {
|
switch (type) {
|
||||||
if (CEF_CURRENTLY_ON_UIT()) {
|
case ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER:
|
||||||
CancelNow(std::move(callback_));
|
mode = FileChooserParams::Mode::kUploadFolder;
|
||||||
} else {
|
break;
|
||||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(&UploadFolderHelper::CancelNow,
|
case ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE:
|
||||||
std::move(callback_)));
|
mode = FileChooserParams::Mode::kSave;
|
||||||
|
break;
|
||||||
|
case ui::SelectFileDialog::Type::SELECT_OPEN_FILE:
|
||||||
|
mode = FileChooserParams::Mode::kOpen;
|
||||||
|
break;
|
||||||
|
case ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE:
|
||||||
|
mode = FileChooserParams::Mode::kOpenMultiple;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.mode = *mode;
|
||||||
|
params.title = title;
|
||||||
|
params.default_file_name = default_path;
|
||||||
|
|
||||||
|
// Note that this translation will lose any mime-type based filters that
|
||||||
|
// may have existed in the original FileChooserParams::accept_types if this
|
||||||
|
// dialog was created via FileSelectHelper::RunFileChooser.
|
||||||
|
if (file_types) {
|
||||||
|
// A list of allowed extensions. For example, it might be
|
||||||
|
// { { "htm", "html" }, { "txt" } }
|
||||||
|
for (auto& vec : file_types->extensions) {
|
||||||
|
for (auto& ext : vec) {
|
||||||
|
params.accept_types.push_back(
|
||||||
|
FilePathTypeToString16(FILE_PATH_LITERAL(".") + ext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnListFile(
|
return params;
|
||||||
const net::DirectoryLister::DirectoryListerData& data) override {
|
}
|
||||||
CEF_REQUIRE_UIT();
|
|
||||||
if (!data.info.IsDirectory())
|
|
||||||
select_files_.push_back(data.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnListDone(int error) override {
|
class CefFileSelectListener : public content::FileSelectListener {
|
||||||
CEF_REQUIRE_UIT();
|
public:
|
||||||
if (!callback_.is_null()) {
|
using CallbackType = CefFileDialogManager::RunFileChooserCallback;
|
||||||
std::move(callback_).Run(0, select_files_);
|
|
||||||
}
|
explicit CefFileSelectListener(CallbackType callback)
|
||||||
}
|
: callback_(std::move(callback)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void CancelNow(CefFileDialogRunner::RunFileChooserCallback callback) {
|
~CefFileSelectListener() override = default;
|
||||||
CEF_REQUIRE_UIT();
|
|
||||||
std::vector<base::FilePath> file_paths;
|
void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||||
std::move(callback).Run(0, file_paths);
|
const base::FilePath& base_dir,
|
||||||
|
FileChooserParams::Mode mode) override {
|
||||||
|
std::vector<base::FilePath> paths;
|
||||||
|
if (mode == FileChooserParams::Mode::kUploadFolder) {
|
||||||
|
if (!base_dir.empty()) {
|
||||||
|
paths.push_back(base_dir);
|
||||||
|
}
|
||||||
|
} else if (!files.empty()) {
|
||||||
|
for (auto& file : files) {
|
||||||
|
if (file->is_native_file()) {
|
||||||
|
paths.push_back(file->get_native_file()->file_path);
|
||||||
|
} else {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::move(callback_).Run(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback_;
|
void FileSelectionCanceled() override { std::move(callback_).Run({}); }
|
||||||
std::vector<base::FilePath> select_files_;
|
|
||||||
|
CallbackType callback_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CefFileDialogManager::CefFileDialogManager(
|
class CefSelectFileDialogListener : public ui::SelectFileDialog::Listener {
|
||||||
AlloyBrowserHostImpl* browser,
|
public:
|
||||||
std::unique_ptr<CefFileDialogRunner> runner)
|
CefSelectFileDialogListener(ui::SelectFileDialog::Listener* listener,
|
||||||
: browser_(browser),
|
void* params,
|
||||||
runner_(std::move(runner)),
|
base::OnceClosure callback)
|
||||||
file_chooser_pending_(false),
|
: listener_(listener), params_(params), callback_(std::move(callback)) {}
|
||||||
weak_ptr_factory_(this) {}
|
|
||||||
|
|
||||||
CefFileDialogManager::~CefFileDialogManager() {}
|
CefSelectFileDialogListener(const CefSelectFileDialogListener&) = delete;
|
||||||
|
CefSelectFileDialogListener& operator=(const CefSelectFileDialogListener&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
void Cancel(bool listener_destroyed) {
|
||||||
|
if (executing_) {
|
||||||
|
// We're likely still on the stack. Do nothing and wait for Destroy().
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (listener_destroyed) {
|
||||||
|
// Don't execute the listener.
|
||||||
|
Destroy();
|
||||||
|
} else {
|
||||||
|
FileSelectionCanceled(params_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::SelectFileDialog::Listener* listener() const { return listener_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
~CefSelectFileDialogListener() override = default;
|
||||||
|
|
||||||
|
void FileSelected(const base::FilePath& path,
|
||||||
|
int index,
|
||||||
|
void* params) override {
|
||||||
|
DCHECK_EQ(params, params_);
|
||||||
|
executing_ = true;
|
||||||
|
listener_->FileSelected(path, index, params);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file,
|
||||||
|
int index,
|
||||||
|
void* params) override {
|
||||||
|
DCHECK_EQ(params, params_);
|
||||||
|
executing_ = true;
|
||||||
|
listener_->FileSelectedWithExtraInfo(file, index, params);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiFilesSelected(const std::vector<base::FilePath>& files,
|
||||||
|
void* params) override {
|
||||||
|
DCHECK_EQ(params, params_);
|
||||||
|
executing_ = true;
|
||||||
|
listener_->MultiFilesSelected(files, params);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiFilesSelectedWithExtraInfo(
|
||||||
|
const std::vector<ui::SelectedFileInfo>& files,
|
||||||
|
void* params) override {
|
||||||
|
DCHECK_EQ(params, params_);
|
||||||
|
executing_ = true;
|
||||||
|
listener_->MultiFilesSelectedWithExtraInfo(files, params);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelectionCanceled(void* params) override {
|
||||||
|
DCHECK_EQ(params, params_);
|
||||||
|
executing_ = true;
|
||||||
|
listener_->FileSelectionCanceled(params);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy() {
|
||||||
|
std::move(callback_).Run();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::SelectFileDialog::Listener* const listener_;
|
||||||
|
void* const params_;
|
||||||
|
base::OnceClosure callback_;
|
||||||
|
|
||||||
|
// Used to avoid re-entrancy from Cancel().
|
||||||
|
bool executing_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CefFileDialogManager::CefFileDialogManager(CefBrowserHostBase* browser)
|
||||||
|
: browser_(browser) {}
|
||||||
|
|
||||||
|
CefFileDialogManager::~CefFileDialogManager() = default;
|
||||||
|
|
||||||
void CefFileDialogManager::Destroy() {
|
void CefFileDialogManager::Destroy() {
|
||||||
DCHECK(!file_chooser_pending_);
|
if (dialog_listener_) {
|
||||||
runner_.reset(nullptr);
|
// Cancel the listener and delete related objects.
|
||||||
|
SelectFileDoneByListenerCallback(/*listener_destroyed=*/false);
|
||||||
|
}
|
||||||
|
DCHECK(!dialog_);
|
||||||
|
DCHECK(!dialog_listener_);
|
||||||
|
DCHECK(active_listeners_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefFileDialogManager::RunFileDialog(
|
void CefFileDialogManager::RunFileDialog(
|
||||||
@ -160,14 +296,13 @@ void CefFileDialogManager::RunFileDialog(
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get())
|
if (!callback.get())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CefFileDialogRunner::FileChooserParams params;
|
blink::mojom::FileChooserParams params;
|
||||||
switch (mode & FILE_DIALOG_TYPE_MASK) {
|
switch (mode) {
|
||||||
case FILE_DIALOG_OPEN:
|
case FILE_DIALOG_OPEN:
|
||||||
params.mode = blink::mojom::FileChooserParams::Mode::kOpen;
|
params.mode = blink::mojom::FileChooserParams::Mode::kOpen;
|
||||||
break;
|
break;
|
||||||
@ -182,12 +317,6 @@ void CefFileDialogManager::RunFileDialog(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
params.selected_accept_filter = selected_accept_filter;
|
|
||||||
|
|
||||||
params.overwriteprompt = !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
|
||||||
params.hidereadonly = !!(mode & FILE_DIALOG_HIDEREADONLY_FLAG);
|
|
||||||
|
|
||||||
params.title = title;
|
params.title = title;
|
||||||
if (!default_file_path.empty())
|
if (!default_file_path.empty())
|
||||||
params.default_file_name = base::FilePath(default_file_path);
|
params.default_file_name = base::FilePath(default_file_path);
|
||||||
@ -202,55 +331,145 @@ void CefFileDialogManager::RunFileDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefFileDialogManager::RunFileChooser(
|
void CefFileDialogManager::RunFileChooser(
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
const blink::mojom::FileChooserParams& params,
|
||||||
const blink::mojom::FileChooserParams& params) {
|
RunFileChooserCallback callback) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
CefFileDialogRunner::FileChooserParams cef_params;
|
// Execute the delegate with the most exact version of |params|. If not
|
||||||
static_cast<blink::mojom::FileChooserParams&>(cef_params) = params;
|
// handled here there will be another call to the delegate from RunSelectFile.
|
||||||
|
// It might be better to execute the delegate only the single time here, but
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback;
|
// we don't currently have sufficient state in RunSelectFile to know that the
|
||||||
if (params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
// delegate has already been executed.
|
||||||
callback = base::BindOnce(
|
callback = MaybeRunDelegate(params, std::move(callback));
|
||||||
&CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback,
|
if (callback.is_null()) {
|
||||||
weak_ptr_factory_.GetWeakPtr(), params.mode, listener);
|
// The delegate kept the callback.
|
||||||
} else {
|
|
||||||
callback =
|
|
||||||
base::BindOnce(&CefFileDialogManager::OnRunFileChooserDelegateCallback,
|
|
||||||
weak_ptr_factory_.GetWeakPtr(), params.mode, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunFileChooserInternal(cef_params, std::move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefFileDialogManager::RunFileChooser(
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback) {
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback host_callback =
|
|
||||||
base::BindOnce(&CefFileDialogManager::OnRunFileChooserCallback,
|
|
||||||
weak_ptr_factory_.GetWeakPtr(), std::move(callback));
|
|
||||||
RunFileChooserInternal(params, std::move(host_callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefFileDialogManager::RunFileChooserInternal(
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback) {
|
|
||||||
CEF_REQUIRE_UIT();
|
|
||||||
|
|
||||||
if (file_chooser_pending_) {
|
|
||||||
// Dismiss the new dialog immediately.
|
|
||||||
std::move(callback).Run(0, std::vector<base::FilePath>());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_chooser_pending_ = true;
|
FileChooserParams new_params = params;
|
||||||
|
|
||||||
bool handled = false;
|
// Make sure we get native files in CefFileSelectListener.
|
||||||
|
new_params.need_local_path = true;
|
||||||
|
|
||||||
if (browser_->client().get()) {
|
// Requirements of FileSelectHelper.
|
||||||
CefRefPtr<CefDialogHandler> handler =
|
if (params.mode != FileChooserParams::Mode::kSave) {
|
||||||
browser_->client()->GetDialogHandler();
|
new_params.default_file_name = base::FilePath();
|
||||||
if (handler.get()) {
|
} else {
|
||||||
|
new_params.default_file_name = new_params.default_file_name.BaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileSelectHelper is usually only used for renderer-initiated dialogs via
|
||||||
|
// WebContentsDelegate::RunFileChooser. We choose to use it here instead of
|
||||||
|
// calling ui::SelectFileDialog::Create directly because it provides some nice
|
||||||
|
// functionality related to default dialog settings and filter list
|
||||||
|
// generation. We customize the behavior slightly for non-renderer-initiated
|
||||||
|
// dialogs by passing the |run_from_cef=true| flag. FileSelectHelper uses
|
||||||
|
// ui::SelectFileDialog::Create internally and that call will be intercepted
|
||||||
|
// by CefSelectFileDialogFactory, resulting in call to RunSelectFile below.
|
||||||
|
// See related comments on CefSelectFileDialogFactory.
|
||||||
|
FileSelectHelper::RunFileChooser(
|
||||||
|
browser_->GetWebContents()->GetMainFrame(),
|
||||||
|
base::MakeRefCounted<CefFileSelectListener>(std::move(callback)),
|
||||||
|
new_params, /*run_from_cef=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::RunSelectFile(
|
||||||
|
ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy,
|
||||||
|
ui::SelectFileDialog::Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const ui::SelectFileDialog::FileTypeInfo* file_types,
|
||||||
|
int file_type_index,
|
||||||
|
const base::FilePath::StringType& default_extension,
|
||||||
|
gfx::NativeWindow owning_window,
|
||||||
|
void* params) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
|
active_listeners_.insert(listener);
|
||||||
|
|
||||||
|
// This will not be an exact representation of the original params.
|
||||||
|
auto chooser_params =
|
||||||
|
SelectFileToFileChooserParams(type, title, default_path, file_types);
|
||||||
|
auto callback =
|
||||||
|
base::BindOnce(&CefFileDialogManager::SelectFileDoneByDelegateCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), base::Unretained(listener),
|
||||||
|
base::Unretained(params));
|
||||||
|
callback = MaybeRunDelegate(chooser_params, std::move(callback));
|
||||||
|
if (callback.is_null()) {
|
||||||
|
// The delegate kept the callback.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialog_) {
|
||||||
|
LOG(ERROR) << "Multiple simultaneous dialogs are not supported; "
|
||||||
|
"canceling the file dialog";
|
||||||
|
std::move(callback).Run({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LINUX)
|
||||||
|
// We can't use GtkUi in combination with multi-threaded-message-loop because
|
||||||
|
// Chromium's GTK implementation doesn't use GDK threads.
|
||||||
|
if (!!CefContext::Get()->settings().multi_threaded_message_loop) {
|
||||||
|
LOG(ERROR) << "Default dialog implementation is not available; "
|
||||||
|
"canceling the file dialog";
|
||||||
|
std::move(callback).Run({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// |callback| is no longer used at this point.
|
||||||
|
callback.Reset();
|
||||||
|
|
||||||
|
DCHECK(!dialog_listener_);
|
||||||
|
|
||||||
|
// This object will delete itself.
|
||||||
|
dialog_listener_ = new CefSelectFileDialogListener(
|
||||||
|
listener, params,
|
||||||
|
base::BindOnce(&CefFileDialogManager::SelectFileDoneByListenerCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(),
|
||||||
|
/*listener_destroyed=*/false));
|
||||||
|
|
||||||
|
// This call will not be intercepted by CefSelectFileDialogFactory due to the
|
||||||
|
// |run_from_cef=true| flag.
|
||||||
|
// See related comments on CefSelectFileDialogFactory.
|
||||||
|
dialog_ = ui::SelectFileDialog::Create(dialog_listener_, std::move(policy),
|
||||||
|
/*run_from_cef=*/true);
|
||||||
|
|
||||||
|
// With windowless rendering use the parent handle specified by the client.
|
||||||
|
if (browser_->IsWindowless()) {
|
||||||
|
DCHECK(!owning_window);
|
||||||
|
dialog_->set_owning_widget(browser_->GetWindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_->SelectFile(type, title, default_path, file_types, file_type_index,
|
||||||
|
default_extension, owning_window, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::SelectFileListenerDestroyed(
|
||||||
|
ui::SelectFileDialog::Listener* listener) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
DCHECK(listener);
|
||||||
|
|
||||||
|
// This notification will arrive from whomever owns |listener|, so we don't
|
||||||
|
// want to execute any |listener| methods after this point.
|
||||||
|
if (dialog_listener_ && listener == dialog_listener_->listener()) {
|
||||||
|
// Cancel the currently active dialog.
|
||||||
|
SelectFileDoneByListenerCallback(/*listener_destroyed=*/true);
|
||||||
|
} else {
|
||||||
|
// Any future SelectFileDoneByDelegateCallback call for |listener| becomes a
|
||||||
|
// no-op.
|
||||||
|
active_listeners_.erase(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFileDialogManager::RunFileChooserCallback
|
||||||
|
CefFileDialogManager::MaybeRunDelegate(
|
||||||
|
const blink::mojom::FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) {
|
||||||
|
if (auto client = browser_->client()) {
|
||||||
|
if (auto handler = browser_->client()->GetDialogHandler()) {
|
||||||
int mode = FILE_DIALOG_OPEN;
|
int mode = FILE_DIALOG_OPEN;
|
||||||
switch (params.mode) {
|
switch (params.mode) {
|
||||||
case blink::mojom::FileChooserParams::Mode::kOpen:
|
case blink::mojom::FileChooserParams::Mode::kOpen:
|
||||||
@ -270,11 +489,6 @@ void CefFileDialogManager::RunFileChooserInternal(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.overwriteprompt)
|
|
||||||
mode |= FILE_DIALOG_OVERWRITEPROMPT_FLAG;
|
|
||||||
if (params.hidereadonly)
|
|
||||||
mode |= FILE_DIALOG_HIDEREADONLY_FLAG;
|
|
||||||
|
|
||||||
std::vector<std::u16string>::const_iterator it;
|
std::vector<std::u16string>::const_iterator it;
|
||||||
|
|
||||||
std::vector<CefString> accept_filters;
|
std::vector<CefString> accept_filters;
|
||||||
@ -284,10 +498,9 @@ void CefFileDialogManager::RunFileChooserInternal(
|
|||||||
|
|
||||||
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
|
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
|
||||||
new CefFileDialogCallbackImpl(std::move(callback)));
|
new CefFileDialogCallbackImpl(std::move(callback)));
|
||||||
handled = handler->OnFileDialog(
|
const bool handled = handler->OnFileDialog(
|
||||||
browser_, static_cast<cef_file_dialog_mode_t>(mode), params.title,
|
browser_, static_cast<cef_file_dialog_mode_t>(mode), params.title,
|
||||||
params.default_file_name.value(), accept_filters,
|
params.default_file_name.value(), accept_filters, callbackImpl.get());
|
||||||
params.selected_accept_filter, callbackImpl.get());
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
// May return nullptr if the client has already executed the callback.
|
// May return nullptr if the client has already executed the callback.
|
||||||
callback = callbackImpl->Disconnect();
|
callback = callbackImpl->Disconnect();
|
||||||
@ -295,82 +508,57 @@ void CefFileDialogManager::RunFileChooserInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled && !callback.is_null()) {
|
return callback;
|
||||||
if (runner_.get()) {
|
|
||||||
runner_->Run(browser_, params, std::move(callback));
|
|
||||||
} else {
|
|
||||||
LOG(WARNING) << "No file dialog runner available for this platform";
|
|
||||||
std::move(callback).Run(0, std::vector<base::FilePath>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefFileDialogManager::OnRunFileChooserCallback(
|
void CefFileDialogManager::SelectFileDoneByDelegateCallback(
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback,
|
ui::SelectFileDialog::Listener* listener,
|
||||||
int selected_accept_filter,
|
void* params,
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& paths) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
Cleanup();
|
// The listener may already be gone. This can occur if the client holds a
|
||||||
|
// RunFileChooserCallback past the call to SelectFileListenerDestroyed().
|
||||||
|
if (active_listeners_.find(listener) == active_listeners_.end())
|
||||||
|
return;
|
||||||
|
|
||||||
// Execute the callback asynchronously.
|
active_listeners_.erase(listener);
|
||||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(std::move(callback),
|
|
||||||
selected_accept_filter, file_paths));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback(
|
if (paths.empty()) {
|
||||||
const blink::mojom::FileChooserParams::Mode mode,
|
listener->FileSelectionCanceled(params);
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
} else if (paths.size() == 1) {
|
||||||
int selected_accept_filter,
|
listener->FileSelected(paths[0], /*index=*/0, params);
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
|
||||||
CEF_REQUIRE_UIT();
|
|
||||||
DCHECK_EQ(mode, blink::mojom::FileChooserParams::Mode::kUploadFolder);
|
|
||||||
|
|
||||||
if (file_paths.size() == 0) {
|
|
||||||
// Client canceled the file chooser.
|
|
||||||
OnRunFileChooserDelegateCallback(mode, listener, selected_accept_filter,
|
|
||||||
file_paths);
|
|
||||||
} else {
|
} else {
|
||||||
lister_.reset(new net::DirectoryLister(
|
listener->MultiFilesSelected(paths, params);
|
||||||
file_paths[0], net::DirectoryLister::NO_SORT_RECURSIVE,
|
|
||||||
new UploadFolderHelper(base::BindOnce(
|
|
||||||
&CefFileDialogManager::OnRunFileChooserDelegateCallback,
|
|
||||||
weak_ptr_factory_.GetWeakPtr(), mode, listener))));
|
|
||||||
lister_->Start();
|
|
||||||
}
|
}
|
||||||
|
// |listener| is likely deleted at this point.
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefFileDialogManager::OnRunFileChooserDelegateCallback(
|
void CefFileDialogManager::SelectFileDoneByListenerCallback(
|
||||||
blink::mojom::FileChooserParams::Mode mode,
|
bool listener_destroyed) {
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
base::FilePath base_dir;
|
// Avoid re-entrancy of this method. CefSelectFileDialogListener callbacks to
|
||||||
std::vector<blink::mojom::FileChooserFileInfoPtr> selected_files;
|
// the delegated listener may result in an immediate call to
|
||||||
|
// SelectFileListenerDestroyed() while |dialog_listener_| is still on the
|
||||||
|
// stack, followed by another execution from
|
||||||
|
// CefSelectFileDialogListener::Destroy(). Similarly, the below call to
|
||||||
|
// Cancel() may trigger another execution from
|
||||||
|
// CefSelectFileDialogListener::Destroy().
|
||||||
|
if (!dialog_listener_)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!file_paths.empty()) {
|
DCHECK(dialog_);
|
||||||
if (mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
DCHECK(dialog_listener_);
|
||||||
base_dir = file_paths[0].DirName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert FilePath list to SelectedFileInfo list.
|
active_listeners_.erase(dialog_listener_->listener());
|
||||||
for (size_t i = 0; i < file_paths.size(); ++i) {
|
|
||||||
auto info = blink::mojom::FileChooserFileInfo::NewNativeFile(
|
|
||||||
blink::mojom::NativeFileInfo::New(file_paths[i], std::u16string()));
|
|
||||||
selected_files.push_back(std::move(info));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listener->FileSelected(std::move(selected_files), base_dir, mode);
|
// Clear |dialog_listener_| before calling Cancel() to avoid re-entrancy.
|
||||||
|
auto dialog_listener = dialog_listener_;
|
||||||
|
dialog_listener_ = nullptr;
|
||||||
|
dialog_listener->Cancel(listener_destroyed);
|
||||||
|
|
||||||
Cleanup();
|
// There should be no further listener callbacks after this call.
|
||||||
}
|
dialog_->ListenerDestroyed();
|
||||||
|
dialog_ = nullptr;
|
||||||
void CefFileDialogManager::Cleanup() {
|
|
||||||
if (lister_)
|
|
||||||
lister_.reset();
|
|
||||||
|
|
||||||
file_chooser_pending_ = false;
|
|
||||||
}
|
}
|
||||||
|
@ -7,28 +7,25 @@
|
|||||||
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_MANAGER_H_
|
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_MANAGER_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "include/cef_browser.h"
|
#include <memory>
|
||||||
#include "libcef/browser/file_dialog_runner.h"
|
#include <set>
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "include/cef_browser.h"
|
||||||
#include "content/public/browser/web_contents_observer.h"
|
|
||||||
|
#include "base/memory/scoped_refptr.h"
|
||||||
|
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_dialog.h"
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class FileSelectListener;
|
class FileSelectListener;
|
||||||
class WebContents;
|
|
||||||
} // namespace content
|
} // namespace content
|
||||||
|
|
||||||
namespace net {
|
class CefBrowserHostBase;
|
||||||
class DirectoryLister;
|
class CefSelectFileDialogListener;
|
||||||
}
|
|
||||||
|
|
||||||
class AlloyBrowserHostImpl;
|
|
||||||
|
|
||||||
class CefFileDialogManager {
|
class CefFileDialogManager {
|
||||||
public:
|
public:
|
||||||
// |runner| may be NULL if the platform doesn't implement dialogs.
|
explicit CefFileDialogManager(CefBrowserHostBase* browser);
|
||||||
CefFileDialogManager(AlloyBrowserHostImpl* browser,
|
|
||||||
std::unique_ptr<CefFileDialogRunner> runner);
|
|
||||||
|
|
||||||
CefFileDialogManager(const CefFileDialogManager&) = delete;
|
CefFileDialogManager(const CefFileDialogManager&) = delete;
|
||||||
CefFileDialogManager& operator=(const CefFileDialogManager&) = delete;
|
CefFileDialogManager& operator=(const CefFileDialogManager&) = delete;
|
||||||
@ -38,70 +35,65 @@ class CefFileDialogManager {
|
|||||||
// Delete the runner to free any platform constructs.
|
// Delete the runner to free any platform constructs.
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
// Called from AlloyBrowserHostImpl::RunFileChooser.
|
// Run a file dialog with the specified parameters. See
|
||||||
// See CefBrowserHost::RunFileDialog documentation.
|
// CefBrowserHost::RunFileDialog for usage documentation. This method should
|
||||||
|
// be called via CefBrowserHostBase::RunFileDialog.
|
||||||
void RunFileDialog(cef_file_dialog_mode_t mode,
|
void RunFileDialog(cef_file_dialog_mode_t mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback);
|
CefRefPtr<CefRunFileDialogCallback> callback);
|
||||||
|
|
||||||
// Called from AlloyBrowserHostImpl::RunFileChooser.
|
// The argument vector will be empty if the dialog was canceled.
|
||||||
// See WebContentsDelegate::RunFileChooser documentation.
|
using RunFileChooserCallback =
|
||||||
void RunFileChooser(scoped_refptr<content::FileSelectListener> listener,
|
base::OnceCallback<void(const std::vector<base::FilePath>&)>;
|
||||||
const blink::mojom::FileChooserParams& params);
|
|
||||||
|
|
||||||
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
// Run the file dialog specified by |params|. |callback| will be executed
|
||||||
// be pending at any given time. |callback| will be executed asynchronously
|
// synchronously or asynchronously after the dialog is dismissed. This method
|
||||||
// after the dialog is dismissed or if another dialog is already pending.
|
// should be called via CefBrowserHostBase::RunFileChooser.
|
||||||
void RunFileChooser(const CefFileDialogRunner::FileChooserParams& params,
|
void RunFileChooser(const blink::mojom::FileChooserParams& params,
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback);
|
RunFileChooserCallback callback);
|
||||||
|
|
||||||
|
// Run a ui::SelectFileDialog with the specified parameters. See
|
||||||
|
// ui::SelectFileDialog for usage documentation. This method should be called
|
||||||
|
// via CefBrowserHostBase::RunSelectFile. It will be called for all file
|
||||||
|
// dialogs after interception via CefSelectFileDialog::SelectFileImpl.
|
||||||
|
void RunSelectFile(ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy,
|
||||||
|
ui::SelectFileDialog::Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const ui::SelectFileDialog::FileTypeInfo* file_types,
|
||||||
|
int file_type_index,
|
||||||
|
const base::FilePath::StringType& default_extension,
|
||||||
|
gfx::NativeWindow owning_window,
|
||||||
|
void* params);
|
||||||
|
|
||||||
|
// Must be called when the |listener| passed to RunSelectFile is destroyed.
|
||||||
|
void SelectFileListenerDestroyed(ui::SelectFileDialog::Listener* listener);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RunFileChooserInternal(
|
[[nodiscard]] RunFileChooserCallback MaybeRunDelegate(
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
const blink::mojom::FileChooserParams& params,
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback);
|
RunFileChooserCallback callback);
|
||||||
|
|
||||||
// Used with the RunFileChooser variant where the caller specifies a callback
|
void SelectFileDoneByDelegateCallback(
|
||||||
// (no associated RenderFrameHost).
|
ui::SelectFileDialog::Listener* listener,
|
||||||
void OnRunFileChooserCallback(
|
void* params,
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback,
|
const std::vector<base::FilePath>& paths);
|
||||||
int selected_accept_filter,
|
void SelectFileDoneByListenerCallback(bool listener_destroyed);
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
// Used with WebContentsDelegate::RunFileChooser when mode is
|
// CefBrowserHostBase pointer is guaranteed to outlive this object.
|
||||||
// blink::mojom::FileChooserParams::Mode::kUploadFolder.
|
CefBrowserHostBase* const browser_;
|
||||||
void OnRunFileChooserUploadFolderDelegateCallback(
|
|
||||||
const blink::mojom::FileChooserParams::Mode mode,
|
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
// Used with WebContentsDelegate::RunFileChooser to notify the
|
// Used when running a platform dialog via RunSelectFile.
|
||||||
// RenderFrameHost.
|
scoped_refptr<ui::SelectFileDialog> dialog_;
|
||||||
void OnRunFileChooserDelegateCallback(
|
CefSelectFileDialogListener* dialog_listener_ = nullptr;
|
||||||
blink::mojom::FileChooserParams::Mode mode,
|
|
||||||
scoped_refptr<content::FileSelectListener> listener,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
// Clean up state associated with the last run.
|
// List of all currently active listeners.
|
||||||
void Cleanup();
|
std::set<ui::SelectFileDialog::Listener*> active_listeners_;
|
||||||
|
|
||||||
// AlloyBrowserHostImpl pointer is guaranteed to outlive this object.
|
base::WeakPtrFactory<CefFileDialogManager> weak_ptr_factory_{this};
|
||||||
AlloyBrowserHostImpl* browser_;
|
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner> runner_;
|
|
||||||
|
|
||||||
// True if a file chooser is currently pending.
|
|
||||||
bool file_chooser_pending_;
|
|
||||||
|
|
||||||
// Used for asynchronously listing directory contents.
|
|
||||||
std::unique_ptr<net::DirectoryLister> lister_;
|
|
||||||
|
|
||||||
// Must be the last member.
|
|
||||||
base::WeakPtrFactory<CefFileDialogManager> weak_ptr_factory_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
|
#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
|
||||||
|
189
libcef/browser/file_dialog_runner.cc
Normal file
189
libcef/browser/file_dialog_runner.cc
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
// Copyright (c) 2022 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions 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/file_dialog_runner.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_base.h"
|
||||||
|
#include "libcef/browser/browser_info_manager.h"
|
||||||
|
#include "libcef/browser/extensions/browser_extensions_util.h"
|
||||||
|
|
||||||
|
#include "base/memory/singleton.h"
|
||||||
|
#include "chrome/browser/file_select_helper.h"
|
||||||
|
#include "chrome/browser/ui/chrome_select_file_policy.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_dialog_factory.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_policy.h"
|
||||||
|
|
||||||
|
using blink::mojom::FileChooserParams;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Creation of a file dialog can be triggered via various code paths, but they
|
||||||
|
// all eventually result in a call to ui::SelectFileDialog::Create. We intercept
|
||||||
|
// that call with CefSelectFileDialogFactory and redirect it to
|
||||||
|
// CefFileDialogManager::RunSelectFile. After triggering the CefDialogHandler
|
||||||
|
// callbacks that method calls ui::SelectFileDialog::Create again with
|
||||||
|
// |run_from_cef=false| to trigger creation of the default platform dialog.
|
||||||
|
class CefSelectFileDialogFactory final : public ui::SelectFileDialogFactory {
|
||||||
|
public:
|
||||||
|
CefSelectFileDialogFactory(const CefSelectFileDialogFactory&) = delete;
|
||||||
|
CefSelectFileDialogFactory& operator=(const CefSelectFileDialogFactory&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
static CefSelectFileDialogFactory* GetInstance() {
|
||||||
|
// Leaky because there is no useful cleanup to do.
|
||||||
|
return base::Singleton<
|
||||||
|
CefSelectFileDialogFactory,
|
||||||
|
base::LeakySingletonTraits<CefSelectFileDialogFactory>>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::SelectFileDialog* Create(
|
||||||
|
ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy) override;
|
||||||
|
|
||||||
|
bool IsCefFactory() const override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct base::DefaultSingletonTraits<CefSelectFileDialogFactory>;
|
||||||
|
|
||||||
|
CefSelectFileDialogFactory() { ui::SelectFileDialog::SetFactory(this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> GetBrowserForTopLevelNativeWindow(
|
||||||
|
gfx::NativeWindow owning_window) {
|
||||||
|
DCHECK(owning_window);
|
||||||
|
for (const auto& browser_info :
|
||||||
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
|
||||||
|
if (auto browser = browser_info->browser()) {
|
||||||
|
if (browser->GetTopLevelNativeWindow() == owning_window)
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> GetLikelyFocusedBrowser() {
|
||||||
|
for (const auto& browser_info :
|
||||||
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
|
||||||
|
if (auto browser = browser_info->browser()) {
|
||||||
|
if (browser->IsFocused())
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegates the running of the dialog to CefFileDialogManager.
|
||||||
|
class CefSelectFileDialog final : public ui::SelectFileDialog {
|
||||||
|
public:
|
||||||
|
CefSelectFileDialog(ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy)
|
||||||
|
: ui::SelectFileDialog(listener, std::move(policy)) {
|
||||||
|
DCHECK(listener_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefSelectFileDialog(const CefSelectFileDialog&) = delete;
|
||||||
|
CefSelectFileDialog& operator=(const CefSelectFileDialog&) = delete;
|
||||||
|
|
||||||
|
void SelectFileImpl(Type type,
|
||||||
|
const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const FileTypeInfo* file_types,
|
||||||
|
int file_type_index,
|
||||||
|
const base::FilePath::StringType& default_extension,
|
||||||
|
gfx::NativeWindow owning_window,
|
||||||
|
void* params) override {
|
||||||
|
// Try to determine the associated browser (with decreasing levels of
|
||||||
|
// confidence).
|
||||||
|
// 1. Browser associated with the SelectFilePolicy. This is the most
|
||||||
|
// reliable mechanism if specified at the SelectFileDialog::Create call
|
||||||
|
// site.
|
||||||
|
if (select_file_policy_) {
|
||||||
|
auto chrome_policy =
|
||||||
|
static_cast<ChromeSelectFilePolicy*>(select_file_policy_.get());
|
||||||
|
auto web_contents = chrome_policy->source_contents();
|
||||||
|
if (web_contents) {
|
||||||
|
browser_ = extensions::GetOwnerBrowserForHost(
|
||||||
|
web_contents->GetRenderViewHost(), nullptr);
|
||||||
|
}
|
||||||
|
if (!browser_) {
|
||||||
|
LOG(WARNING) << "No browser associated with SelectFilePolicy";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Browser associated with the top-level native window (owning_window).
|
||||||
|
// This should be reliable with windowed browsers. However, |owning_window|
|
||||||
|
// will always be nullptr with windowless browsers.
|
||||||
|
if (!browser_ && owning_window) {
|
||||||
|
browser_ = GetBrowserForTopLevelNativeWindow(owning_window);
|
||||||
|
if (!browser_) {
|
||||||
|
LOG(WARNING) << "No browser associated with top-level native window";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Browser most likely to be focused. This may be somewhat iffy with
|
||||||
|
// windowless browsers as there is no guarantee that the client has only
|
||||||
|
// one browser focused at a time.
|
||||||
|
if (!browser_) {
|
||||||
|
browser_ = GetLikelyFocusedBrowser();
|
||||||
|
if (!browser_) {
|
||||||
|
LOG(WARNING) << "No likely focused browser";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!browser_) {
|
||||||
|
LOG(ERROR)
|
||||||
|
<< "Failed to identify associated browser; canceling the file dialog";
|
||||||
|
listener_->FileSelectionCanceled(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
owning_window_ = owning_window;
|
||||||
|
has_multiple_file_choices_ =
|
||||||
|
file_types ? file_types->extensions.size() > 1 : true;
|
||||||
|
|
||||||
|
browser_->RunSelectFile(listener_, std::move(select_file_policy_), type,
|
||||||
|
title, default_path, file_types, file_type_index,
|
||||||
|
default_extension, owning_window, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRunning(gfx::NativeWindow owning_window) const override {
|
||||||
|
return owning_window == owning_window_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListenerDestroyed() override {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SelectFileListenerDestroyed(listener_);
|
||||||
|
listener_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasMultipleFileTypeChoicesImpl() override {
|
||||||
|
return has_multiple_file_choices_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
gfx::NativeWindow owning_window_ = nullptr;
|
||||||
|
bool has_multiple_file_choices_ = false;
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser_;
|
||||||
|
};
|
||||||
|
|
||||||
|
ui::SelectFileDialog* CefSelectFileDialogFactory::Create(
|
||||||
|
ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy) {
|
||||||
|
return new CefSelectFileDialog(listener, std::move(policy));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace file_dialog_runner {
|
||||||
|
|
||||||
|
void RegisterFactory() {
|
||||||
|
// Implicitly registers on creation.
|
||||||
|
CefSelectFileDialogFactory::GetInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace file_dialog_runner
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
// Copyright (c) 2022 The Chromium Embedded Framework Authors.
|
||||||
// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
|
// Portions copyright (c) 2012 The Chromium 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 in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
@ -7,46 +7,11 @@
|
|||||||
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
namespace file_dialog_runner {
|
||||||
|
|
||||||
#include "base/callback.h"
|
// One-time registration on startup.
|
||||||
#include "base/files/file_path.h"
|
void RegisterFactory();
|
||||||
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
|
||||||
|
|
||||||
class AlloyBrowserHostImpl;
|
} // namespace file_dialog_runner
|
||||||
|
|
||||||
class CefFileDialogRunner {
|
|
||||||
public:
|
|
||||||
CefFileDialogRunner(const CefFileDialogRunner&) = delete;
|
|
||||||
CefFileDialogRunner& operator=(const CefFileDialogRunner&) = delete;
|
|
||||||
|
|
||||||
// Extend blink::mojom::FileChooserParams with some options unique to CEF.
|
|
||||||
struct FileChooserParams : public blink::mojom::FileChooserParams {
|
|
||||||
// 0-based index of the selected value in |accept_types|.
|
|
||||||
int selected_accept_filter = 0;
|
|
||||||
|
|
||||||
// True if the Save dialog should prompt before overwriting files.
|
|
||||||
bool overwriteprompt = true;
|
|
||||||
|
|
||||||
// True if read-only files should be hidden.
|
|
||||||
bool hidereadonly = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The argument vector will be empty if the dialog was canceled.
|
|
||||||
using RunFileChooserCallback =
|
|
||||||
base::OnceCallback<void(int, const std::vector<base::FilePath>&)>;
|
|
||||||
|
|
||||||
// Display the file chooser dialog. Execute |callback| on completion.
|
|
||||||
virtual void Run(AlloyBrowserHostImpl* browser,
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Allow deletion via std::unique_ptr only.
|
|
||||||
friend std::default_delete<CefFileDialogRunner>;
|
|
||||||
|
|
||||||
CefFileDialogRunner() = default;
|
|
||||||
virtual ~CefFileDialogRunner() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
#endif // CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
||||||
|
@ -40,7 +40,6 @@ class CefBrowserPlatformDelegateNativeMac
|
|||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const override;
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
||||||
override;
|
override;
|
||||||
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/native/file_dialog_runner_mac.h"
|
|
||||||
#include "libcef/browser/native/javascript_dialog_runner_mac.h"
|
#include "libcef/browser/native/javascript_dialog_runner_mac.h"
|
||||||
#include "libcef/browser/native/menu_runner_mac.h"
|
#include "libcef/browser/native/menu_runner_mac.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
@ -363,11 +362,6 @@ CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle(
|
|||||||
return event.os_event;
|
return event.os_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegateNativeMac::CreateFileDialogRunner() {
|
|
||||||
return base::WrapUnique(new CefFileDialogRunnerMac);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegateNativeMac::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegateNativeMac::CreateJavaScriptDialogRunner() {
|
||||||
return base::WrapUnique(new CefJavaScriptDialogRunnerMac);
|
return base::WrapUnique(new CefJavaScriptDialogRunnerMac);
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/native/file_dialog_runner_win.h"
|
|
||||||
#include "libcef/browser/native/javascript_dialog_runner_win.h"
|
#include "libcef/browser/native/javascript_dialog_runner_win.h"
|
||||||
#include "libcef/browser/native/menu_runner_win.h"
|
#include "libcef/browser/native/menu_runner_win.h"
|
||||||
#include "libcef/browser/native/window_delegate_view.h"
|
#include "libcef/browser/native/window_delegate_view.h"
|
||||||
@ -447,11 +446,6 @@ CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle(
|
|||||||
const_cast<CHROME_MSG*>(&event.os_event->native_event()));
|
const_cast<CHROME_MSG*>(&event.os_event->native_event()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegateNativeWin::CreateFileDialogRunner() {
|
|
||||||
return base::WrapUnique(new CefFileDialogRunnerWin);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegateNativeWin::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegateNativeWin::CreateJavaScriptDialogRunner() {
|
||||||
return base::WrapUnique(new CefJavaScriptDialogRunnerWin);
|
return base::WrapUnique(new CefJavaScriptDialogRunnerWin);
|
||||||
|
@ -34,7 +34,6 @@ class CefBrowserPlatformDelegateNativeWin
|
|||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const override;
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
||||||
override;
|
override;
|
||||||
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions 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_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "libcef/browser/file_dialog_runner.h"
|
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
|
||||||
|
|
||||||
@class NSView;
|
|
||||||
|
|
||||||
class CefFileDialogRunnerMac : public CefFileDialogRunner {
|
|
||||||
public:
|
|
||||||
CefFileDialogRunnerMac();
|
|
||||||
|
|
||||||
// CefFileDialogRunner methods:
|
|
||||||
void Run(AlloyBrowserHostImpl* browser,
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void RunOpenFileDialog(
|
|
||||||
base::WeakPtr<CefFileDialogRunnerMac> weak_this,
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int filter_index);
|
|
||||||
static void RunSaveFileDialog(
|
|
||||||
base::WeakPtr<CefFileDialogRunnerMac> weak_this,
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int filter_index);
|
|
||||||
|
|
||||||
CefFileDialogRunner::RunFileChooserCallback callback_;
|
|
||||||
base::WeakPtrFactory<CefFileDialogRunnerMac> weak_ptr_factory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
|
@ -1,405 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions 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/native/file_dialog_runner_mac.h"
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <CoreServices/CoreServices.h>
|
|
||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
|
||||||
|
|
||||||
#include "base/mac/mac_util.h"
|
|
||||||
#include "base/stl_util.h"
|
|
||||||
#include "base/strings/string_split.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
#include "base/strings/sys_string_conversions.h"
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
|
||||||
#include "base/threading/thread_restrictions.h"
|
|
||||||
#include "cef/grit/cef_strings.h"
|
|
||||||
#include "chrome/grit/generated_resources.h"
|
|
||||||
#include "net/base/mime_util.h"
|
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
|
||||||
#include "ui/strings/grit/ui_strings.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
std::u16string GetDescriptionFromMimeType(const std::string& mime_type) {
|
|
||||||
// Check for wild card mime types and return an appropriate description.
|
|
||||||
static const struct {
|
|
||||||
const char* mime_type;
|
|
||||||
int string_id;
|
|
||||||
} kWildCardMimeTypes[] = {
|
|
||||||
{"audio", IDS_AUDIO_FILES},
|
|
||||||
{"image", IDS_IMAGE_FILES},
|
|
||||||
{"text", IDS_TEXT_FILES},
|
|
||||||
{"video", IDS_VIDEO_FILES},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < std::size(kWildCardMimeTypes); ++i) {
|
|
||||||
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
|
|
||||||
return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::u16string();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddFilters(NSPopUpButton* button,
|
|
||||||
const std::vector<std::u16string>& accept_filters,
|
|
||||||
bool include_all_files,
|
|
||||||
std::vector<std::vector<std::u16string>>* all_extensions) {
|
|
||||||
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
|
||||||
const std::u16string& filter = accept_filters[i];
|
|
||||||
if (filter.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::vector<std::u16string> extensions;
|
|
||||||
std::u16string description;
|
|
||||||
|
|
||||||
size_t sep_index = filter.find('|');
|
|
||||||
if (sep_index != std::string::npos) {
|
|
||||||
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
|
||||||
description = filter.substr(0, sep_index);
|
|
||||||
|
|
||||||
const std::vector<std::u16string>& ext =
|
|
||||||
base::SplitString(filter.substr(sep_index + 1), u";",
|
|
||||||
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
|
||||||
const std::u16string& file_ext = ext[x];
|
|
||||||
if (!file_ext.empty() && file_ext[0] == '.')
|
|
||||||
extensions.push_back(file_ext);
|
|
||||||
}
|
|
||||||
} else if (filter[0] == '.') {
|
|
||||||
// Treat as an extension beginning with the '.' character.
|
|
||||||
extensions.push_back(filter);
|
|
||||||
} else {
|
|
||||||
// Otherwise convert mime type to one or more extensions.
|
|
||||||
const std::string& ascii = base::UTF16ToASCII(filter);
|
|
||||||
std::vector<base::FilePath::StringType> ext;
|
|
||||||
net::GetExtensionsForMimeType(ascii, &ext);
|
|
||||||
if (!ext.empty()) {
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x)
|
|
||||||
extensions.push_back(u"." + base::ASCIIToUTF16(ext[x]));
|
|
||||||
description = GetDescriptionFromMimeType(ascii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensions.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Don't display a crazy number of extensions since the NSPopUpButton width
|
|
||||||
// will keep growing.
|
|
||||||
const size_t kMaxExtensions = 10;
|
|
||||||
|
|
||||||
std::u16string ext_str;
|
|
||||||
for (size_t x = 0; x < std::min(kMaxExtensions, extensions.size()); ++x) {
|
|
||||||
const std::u16string& pattern = u"*" + extensions[x];
|
|
||||||
if (x != 0)
|
|
||||||
ext_str += u";";
|
|
||||||
ext_str += pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensions.size() > kMaxExtensions)
|
|
||||||
ext_str += u";...";
|
|
||||||
|
|
||||||
if (description.empty()) {
|
|
||||||
description = ext_str;
|
|
||||||
} else {
|
|
||||||
description += u" (" + ext_str + u")";
|
|
||||||
}
|
|
||||||
|
|
||||||
[button addItemWithTitle:base::SysUTF16ToNSString(description)];
|
|
||||||
|
|
||||||
all_extensions->push_back(extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the *.* filter, but only if we have added other filters (otherwise it
|
|
||||||
// is implied).
|
|
||||||
if (include_all_files && !all_extensions->empty()) {
|
|
||||||
[button addItemWithTitle:base::SysUTF8ToNSString("All Files (*)")];
|
|
||||||
all_extensions->push_back(std::vector<std::u16string>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// Used to manage the file type filter in the NSSavePanel/NSOpenPanel.
|
|
||||||
@interface CefFilterDelegate : NSObject {
|
|
||||||
@private
|
|
||||||
NSSavePanel* panel_;
|
|
||||||
std::vector<std::vector<std::u16string>> extensions_;
|
|
||||||
int selected_index_;
|
|
||||||
}
|
|
||||||
- (id)initWithPanel:(NSSavePanel*)panel
|
|
||||||
andAcceptFilters:(const std::vector<std::u16string>&)accept_filters
|
|
||||||
andFilterIndex:(int)index;
|
|
||||||
- (void)setFilter:(int)index;
|
|
||||||
- (int)filter;
|
|
||||||
- (void)filterSelectionChanged:(id)sender;
|
|
||||||
- (void)setFileExtension;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CefFilterDelegate
|
|
||||||
|
|
||||||
- (id)initWithPanel:(NSSavePanel*)panel
|
|
||||||
andAcceptFilters:(const std::vector<std::u16string>&)accept_filters
|
|
||||||
andFilterIndex:(int)index {
|
|
||||||
if (self = [super init]) {
|
|
||||||
DCHECK(panel);
|
|
||||||
panel_ = panel;
|
|
||||||
selected_index_ = 0;
|
|
||||||
|
|
||||||
NSPopUpButton* button = [[NSPopUpButton alloc] init];
|
|
||||||
AddFilters(button, accept_filters, true, &extensions_);
|
|
||||||
[button sizeToFit];
|
|
||||||
[button setTarget:self];
|
|
||||||
[button setAction:@selector(filterSelectionChanged:)];
|
|
||||||
|
|
||||||
if (index < static_cast<int>(extensions_.size())) {
|
|
||||||
[button selectItemAtIndex:index];
|
|
||||||
[self setFilter:index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[panel_ setAccessoryView:button];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the current filter index.
|
|
||||||
- (void)setFilter:(int)index {
|
|
||||||
DCHECK(index >= 0 && index < static_cast<int>(extensions_.size()));
|
|
||||||
selected_index_ = index;
|
|
||||||
|
|
||||||
// Set the selectable file types. For open panels this limits the files that
|
|
||||||
// can be selected. For save panels this applies a default file extenion when
|
|
||||||
// the dialog is dismissed if none is already provided.
|
|
||||||
NSMutableArray* acceptArray = nil;
|
|
||||||
if (!extensions_[index].empty()) {
|
|
||||||
acceptArray = [[NSMutableArray alloc] init];
|
|
||||||
for (size_t i = 0; i < extensions_[index].size(); ++i) {
|
|
||||||
[acceptArray
|
|
||||||
addObject:base::SysUTF16ToNSString(extensions_[index][i].substr(1))];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[panel_ setAllowedFileTypes:acceptArray];
|
|
||||||
|
|
||||||
if (![panel_ isKindOfClass:[NSOpenPanel class]]) {
|
|
||||||
// For save panels set the file extension.
|
|
||||||
[self setFileExtension];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the current filter index.
|
|
||||||
- (int)filter {
|
|
||||||
return selected_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the selected filter is changed via the NSPopUpButton.
|
|
||||||
- (void)filterSelectionChanged:(id)sender {
|
|
||||||
NSPopUpButton* button = (NSPopUpButton*)sender;
|
|
||||||
[self setFilter:[button indexOfSelectedItem]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the extension on the currently selected file name.
|
|
||||||
- (void)setFileExtension {
|
|
||||||
const std::vector<std::u16string>& filter = extensions_[selected_index_];
|
|
||||||
if (filter.empty()) {
|
|
||||||
// All extensions are allowed so don't change anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::FilePath path(base::SysNSStringToUTF8([panel_ nameFieldStringValue]));
|
|
||||||
|
|
||||||
// If the file name currently includes an extension from |filter| then don't
|
|
||||||
// change anything.
|
|
||||||
std::u16string extension = base::UTF8ToUTF16(path.Extension());
|
|
||||||
if (!extension.empty()) {
|
|
||||||
for (size_t i = 0; i < filter.size(); ++i) {
|
|
||||||
if (filter[i] == extension)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the extension to the first value in |filter|.
|
|
||||||
path = path.ReplaceExtension(base::UTF16ToUTF8(filter[0]));
|
|
||||||
[panel_ setNameFieldStringValue:base::SysUTF8ToNSString(path.value())];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
CefFileDialogRunnerMac::CefFileDialogRunnerMac() : weak_ptr_factory_(this) {}
|
|
||||||
|
|
||||||
void CefFileDialogRunnerMac::Run(AlloyBrowserHostImpl* browser,
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) {
|
|
||||||
callback_ = std::move(callback);
|
|
||||||
|
|
||||||
int filter_index = params.selected_accept_filter;
|
|
||||||
NSView* owner = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetWindowHandle());
|
|
||||||
auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
|
||||||
|
|
||||||
if (params.mode == blink::mojom::FileChooserParams::Mode::kOpen ||
|
|
||||||
params.mode == blink::mojom::FileChooserParams::Mode::kOpenMultiple ||
|
|
||||||
params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
|
||||||
RunOpenFileDialog(weak_this, params, owner, filter_index);
|
|
||||||
} else if (params.mode == blink::mojom::FileChooserParams::Mode::kSave) {
|
|
||||||
RunSaveFileDialog(weak_this, params, owner, filter_index);
|
|
||||||
} else {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void CefFileDialogRunnerMac::RunOpenFileDialog(
|
|
||||||
base::WeakPtr<CefFileDialogRunnerMac> weak_this,
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int filter_index) {
|
|
||||||
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
|
||||||
|
|
||||||
std::u16string title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = params.title;
|
|
||||||
} else {
|
|
||||||
title = l10n_util::GetStringUTF16(
|
|
||||||
params.mode == blink::mojom::FileChooserParams::Mode::kOpen
|
|
||||||
? IDS_OPEN_FILE_DIALOG_TITLE
|
|
||||||
: (params.mode ==
|
|
||||||
blink::mojom::FileChooserParams::Mode::kOpenMultiple
|
|
||||||
? IDS_OPEN_FILES_DIALOG_TITLE
|
|
||||||
: IDS_SELECT_FOLDER_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
[openPanel setTitle:base::SysUTF16ToNSString(title)];
|
|
||||||
|
|
||||||
std::string filename, directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder ||
|
|
||||||
params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
filename = params.default_file_name.BaseName().value();
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filename.empty()) {
|
|
||||||
[openPanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
|
||||||
}
|
|
||||||
if (!directory.empty()) {
|
|
||||||
[openPanel setDirectoryURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(
|
|
||||||
directory)]];
|
|
||||||
}
|
|
||||||
|
|
||||||
CefFilterDelegate* filter_delegate = nil;
|
|
||||||
if (params.mode != blink::mojom::FileChooserParams::Mode::kUploadFolder &&
|
|
||||||
!params.accept_types.empty()) {
|
|
||||||
// Add the file filter control.
|
|
||||||
filter_delegate =
|
|
||||||
[[CefFilterDelegate alloc] initWithPanel:openPanel
|
|
||||||
andAcceptFilters:params.accept_types
|
|
||||||
andFilterIndex:filter_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Further panel configuration.
|
|
||||||
[openPanel setAllowsOtherFileTypes:YES];
|
|
||||||
[openPanel setAllowsMultipleSelection:
|
|
||||||
(params.mode ==
|
|
||||||
blink::mojom::FileChooserParams::Mode::kOpenMultiple)];
|
|
||||||
[openPanel
|
|
||||||
setCanChooseFiles:(params.mode !=
|
|
||||||
blink::mojom::FileChooserParams::Mode::kUploadFolder)];
|
|
||||||
[openPanel
|
|
||||||
setCanChooseDirectories:(params.mode == blink::mojom::FileChooserParams::
|
|
||||||
Mode::kUploadFolder)];
|
|
||||||
[openPanel setShowsHiddenFiles:!params.hidereadonly];
|
|
||||||
|
|
||||||
// Show panel.
|
|
||||||
[openPanel
|
|
||||||
beginSheetModalForWindow:[view window]
|
|
||||||
completionHandler:^(NSInteger returnCode) {
|
|
||||||
int filter_index_to_use = (filter_delegate != nil)
|
|
||||||
? [filter_delegate filter]
|
|
||||||
: filter_index;
|
|
||||||
if (returnCode == NSFileHandlingPanelOKButton) {
|
|
||||||
std::vector<base::FilePath> files;
|
|
||||||
files.reserve(openPanel.URLs.count);
|
|
||||||
for (NSURL* url in openPanel.URLs) {
|
|
||||||
if (url.isFileURL)
|
|
||||||
files.push_back(base::FilePath(url.path.UTF8String));
|
|
||||||
}
|
|
||||||
std::move(weak_this->callback_)
|
|
||||||
.Run(filter_index_to_use, files);
|
|
||||||
} else {
|
|
||||||
std::move(weak_this->callback_)
|
|
||||||
.Run(filter_index_to_use, std::vector<base::FilePath>());
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void CefFileDialogRunnerMac::RunSaveFileDialog(
|
|
||||||
base::WeakPtr<CefFileDialogRunnerMac> weak_this,
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int filter_index) {
|
|
||||||
NSSavePanel* savePanel = [NSSavePanel savePanel];
|
|
||||||
|
|
||||||
std::u16string title;
|
|
||||||
if (!params.title.empty())
|
|
||||||
title = params.title;
|
|
||||||
else
|
|
||||||
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
|
||||||
[savePanel setTitle:base::SysUTF16ToNSString(title)];
|
|
||||||
|
|
||||||
std::string filename, directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
filename = params.default_file_name.BaseName().value();
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filename.empty()) {
|
|
||||||
[savePanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
|
||||||
}
|
|
||||||
if (!directory.empty()) {
|
|
||||||
[savePanel setDirectoryURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(
|
|
||||||
directory)]];
|
|
||||||
}
|
|
||||||
|
|
||||||
CefFilterDelegate* filter_delegate = nil;
|
|
||||||
if (!params.accept_types.empty()) {
|
|
||||||
// Add the file filter control.
|
|
||||||
filter_delegate =
|
|
||||||
[[CefFilterDelegate alloc] initWithPanel:savePanel
|
|
||||||
andAcceptFilters:params.accept_types
|
|
||||||
andFilterIndex:filter_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[savePanel setAllowsOtherFileTypes:YES];
|
|
||||||
[savePanel setShowsHiddenFiles:!params.hidereadonly];
|
|
||||||
|
|
||||||
// Show panel.
|
|
||||||
[savePanel
|
|
||||||
beginSheetModalForWindow:view.window
|
|
||||||
completionHandler:^(NSInteger resultCode) {
|
|
||||||
int filter_index_to_use = (filter_delegate != nil)
|
|
||||||
? [filter_delegate filter]
|
|
||||||
: filter_index;
|
|
||||||
if (resultCode == NSFileHandlingPanelOKButton) {
|
|
||||||
NSURL* url = savePanel.URL;
|
|
||||||
const char* path = url.path.UTF8String;
|
|
||||||
std::vector<base::FilePath> files(1, base::FilePath(path));
|
|
||||||
std::move(weak_this->callback_)
|
|
||||||
.Run(filter_index_to_use, files);
|
|
||||||
} else {
|
|
||||||
std::move(weak_this->callback_)
|
|
||||||
.Run(filter_index_to_use, std::vector<base::FilePath>());
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
@ -1,560 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions 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/native/file_dialog_runner_win.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <commdlg.h>
|
|
||||||
#include <shlobj.h>
|
|
||||||
#include <wrl/client.h>
|
|
||||||
|
|
||||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
|
||||||
|
|
||||||
#include "base/files/file_util.h"
|
|
||||||
#include "base/stl_util.h"
|
|
||||||
#include "base/strings/string_split.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
|
||||||
#include "base/win/registry.h"
|
|
||||||
#include "cef/grit/cef_strings.h"
|
|
||||||
#include "chrome/grit/generated_resources.h"
|
|
||||||
#include "net/base/mime_util.h"
|
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
|
||||||
#include "ui/base/win/shell.h"
|
|
||||||
#include "ui/strings/grit/ui_strings.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// From ui/base/dialogs/select_file_dialog_win.cc.
|
|
||||||
|
|
||||||
// Get the file type description from the registry. This will be "Text Document"
|
|
||||||
// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
|
|
||||||
// have an entry for the file type, we return false, true if the description was
|
|
||||||
// found. 'file_ext' must be in form ".txt".
|
|
||||||
static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
|
|
||||||
std::wstring* reg_description) {
|
|
||||||
DCHECK(reg_description);
|
|
||||||
base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
|
|
||||||
std::wstring reg_app;
|
|
||||||
if (reg_ext.ReadValue(NULL, ®_app) == ERROR_SUCCESS && !reg_app.empty()) {
|
|
||||||
base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
|
|
||||||
if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file
|
|
||||||
// extensions (internally separated by semicolons), |ext_desc| as the text
|
|
||||||
// descriptions of the |file_ext| types (optional), and (optionally) the default
|
|
||||||
// 'All Files' view. The purpose of the filter is to show only files of a
|
|
||||||
// particular type in a Windows Save/Open dialog box. The resulting filter is
|
|
||||||
// returned. The filters created here are:
|
|
||||||
// 1. only files that have 'file_ext' as their extension
|
|
||||||
// 2. all files (only added if 'include_all_files' is true)
|
|
||||||
// Example:
|
|
||||||
// file_ext: { "*.txt", "*.htm;*.html" }
|
|
||||||
// ext_desc: { "Text Document" }
|
|
||||||
// returned: "Text Document\0*.txt\0HTML Document\0*.htm;*.html\0"
|
|
||||||
// "All Files\0*.*\0\0" (in one big string)
|
|
||||||
// If a description is not provided for a file extension, it will be retrieved
|
|
||||||
// from the registry. If the file extension does not exist in the registry, it
|
|
||||||
// will be omitted from the filter, as it is likely a bogus extension.
|
|
||||||
std::wstring FormatFilterForExtensions(
|
|
||||||
const std::vector<std::wstring>& file_ext,
|
|
||||||
const std::vector<std::wstring>& ext_desc,
|
|
||||||
bool include_all_files) {
|
|
||||||
const std::wstring all_ext = L"*.*";
|
|
||||||
const std::wstring all_desc =
|
|
||||||
base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES)) +
|
|
||||||
L" (" + all_ext + L")";
|
|
||||||
|
|
||||||
DCHECK(file_ext.size() >= ext_desc.size());
|
|
||||||
|
|
||||||
if (file_ext.empty())
|
|
||||||
include_all_files = true;
|
|
||||||
|
|
||||||
std::wstring result;
|
|
||||||
|
|
||||||
// Create all supported .ext filter if more than one filter.
|
|
||||||
if (file_ext.size() > 1) {
|
|
||||||
std::set<base::WStringPiece> unique_exts;
|
|
||||||
for (const auto& exts : file_ext) {
|
|
||||||
for (const auto& ext : base::SplitStringPiece(
|
|
||||||
exts, L";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
|
|
||||||
unique_exts.insert(ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unique_exts.size() > 1) {
|
|
||||||
std::wstring ext;
|
|
||||||
auto it = unique_exts.cbegin();
|
|
||||||
ext = std::wstring(*it);
|
|
||||||
for (++it; it != unique_exts.cend(); ++it) {
|
|
||||||
ext += L";" + std::wstring(*it);
|
|
||||||
}
|
|
||||||
std::wstring desc =
|
|
||||||
base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_CUSTOM_FILES)) +
|
|
||||||
L" (" + ext + L")";
|
|
||||||
|
|
||||||
result.append(desc.c_str(), desc.size() + 1); // Append NULL too.
|
|
||||||
result.append(ext.c_str(), ext.size() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < file_ext.size(); ++i) {
|
|
||||||
std::wstring ext = file_ext[i];
|
|
||||||
std::wstring desc;
|
|
||||||
if (i < ext_desc.size())
|
|
||||||
desc = ext_desc[i];
|
|
||||||
|
|
||||||
if (ext.empty()) {
|
|
||||||
// Force something reasonable to appear in the dialog box if there is no
|
|
||||||
// extension provided.
|
|
||||||
include_all_files = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc.empty()) {
|
|
||||||
DCHECK(ext.find(L'.') != std::wstring::npos);
|
|
||||||
std::wstring first_extension = ext.substr(ext.find(L'.'));
|
|
||||||
size_t first_separator_index = first_extension.find(L';');
|
|
||||||
if (first_separator_index != std::wstring::npos)
|
|
||||||
first_extension = first_extension.substr(0, first_separator_index);
|
|
||||||
|
|
||||||
// Find the extension name without the preceeding '.' character.
|
|
||||||
std::wstring ext_name = first_extension;
|
|
||||||
size_t ext_index = ext_name.find_first_not_of(L'.');
|
|
||||||
if (ext_index != std::wstring::npos)
|
|
||||||
ext_name = ext_name.substr(ext_index);
|
|
||||||
|
|
||||||
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
|
|
||||||
// The extension doesn't exist in the registry.
|
|
||||||
include_all_files = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!desc.empty())
|
|
||||||
desc += L" (" + ext + L")";
|
|
||||||
else
|
|
||||||
desc = ext;
|
|
||||||
|
|
||||||
result.append(desc.c_str(), desc.size() + 1); // Append NULL too.
|
|
||||||
result.append(ext.c_str(), ext.size() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (include_all_files) {
|
|
||||||
result.append(all_desc.c_str(), all_desc.size() + 1);
|
|
||||||
result.append(all_ext.c_str(), all_ext.size() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(1, '\0'); // Double NULL required.
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring GetDescriptionFromMimeType(const std::string& mime_type) {
|
|
||||||
// Check for wild card mime types and return an appropriate description.
|
|
||||||
static const struct {
|
|
||||||
const char* mime_type;
|
|
||||||
int string_id;
|
|
||||||
} kWildCardMimeTypes[] = {
|
|
||||||
{"audio", IDS_AUDIO_FILES},
|
|
||||||
{"image", IDS_IMAGE_FILES},
|
|
||||||
{"text", IDS_TEXT_FILES},
|
|
||||||
{"video", IDS_VIDEO_FILES},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < std::size(kWildCardMimeTypes); ++i) {
|
|
||||||
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*") {
|
|
||||||
return base::UTF16ToWide(
|
|
||||||
l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::wstring();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring GetFilterString(
|
|
||||||
const std::vector<std::u16string>& accept_filters) {
|
|
||||||
std::vector<std::wstring> extensions;
|
|
||||||
std::vector<std::wstring> descriptions;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
|
||||||
const std::wstring& filter = base::UTF16ToWide(accept_filters[i]);
|
|
||||||
if (filter.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
size_t sep_index = filter.find(L'|');
|
|
||||||
if (sep_index != std::wstring::npos) {
|
|
||||||
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
|
||||||
const std::wstring& desc = filter.substr(0, sep_index);
|
|
||||||
const std::vector<std::u16string>& ext = base::SplitString(
|
|
||||||
base::WideToUTF16(filter.substr(sep_index + 1)), u";",
|
|
||||||
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
|
||||||
std::wstring ext_str;
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
|
||||||
const std::wstring& file_ext = base::UTF16ToWide(ext[x]);
|
|
||||||
if (!file_ext.empty() && file_ext[0] == L'.') {
|
|
||||||
if (!ext_str.empty())
|
|
||||||
ext_str += L";";
|
|
||||||
ext_str += L"*" + file_ext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ext_str.empty()) {
|
|
||||||
extensions.push_back(ext_str);
|
|
||||||
descriptions.push_back(desc);
|
|
||||||
}
|
|
||||||
} else if (filter[0] == L'.') {
|
|
||||||
// Treat as an extension beginning with the '.' character.
|
|
||||||
extensions.push_back(L"*" + filter);
|
|
||||||
descriptions.push_back(std::wstring());
|
|
||||||
} else {
|
|
||||||
// Otherwise convert mime type to one or more extensions.
|
|
||||||
const std::string& ascii = base::WideToASCII(filter);
|
|
||||||
std::vector<base::FilePath::StringType> ext;
|
|
||||||
std::wstring ext_str;
|
|
||||||
net::GetExtensionsForMimeType(ascii, &ext);
|
|
||||||
if (!ext.empty()) {
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
|
||||||
if (x != 0)
|
|
||||||
ext_str += L";";
|
|
||||||
ext_str += L"*." + ext[x];
|
|
||||||
}
|
|
||||||
extensions.push_back(ext_str);
|
|
||||||
descriptions.push_back(GetDescriptionFromMimeType(ascii));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FormatFilterForExtensions(extensions, descriptions, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// From chrome/browser/views/shell_dialogs_win.cc
|
|
||||||
|
|
||||||
bool RunOpenFileDialog(const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
HWND owner,
|
|
||||||
int* filter_index,
|
|
||||||
base::FilePath* path) {
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
|
|
||||||
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
|
||||||
// junk in release builds which can cause the Places Bar not to show up!
|
|
||||||
ZeroMemory(&ofn, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = owner;
|
|
||||||
|
|
||||||
wchar_t filename[MAX_PATH] = {0};
|
|
||||||
|
|
||||||
ofn.lpstrFile = filename;
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
|
|
||||||
std::wstring directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
|
||||||
std::size(filename));
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!directory.empty())
|
|
||||||
ofn.lpstrInitialDir = directory.c_str();
|
|
||||||
|
|
||||||
std::wstring title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = base::UTF16ToWide(params.title);
|
|
||||||
} else {
|
|
||||||
title = base::UTF16ToWide(
|
|
||||||
l10n_util::GetStringUTF16(IDS_OPEN_FILE_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
if (!title.empty())
|
|
||||||
ofn.lpstrTitle = title.c_str();
|
|
||||||
|
|
||||||
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
|
||||||
// without having to close Chrome first.
|
|
||||||
ofn.Flags =
|
|
||||||
OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_ENABLESIZING;
|
|
||||||
if (params.hidereadonly)
|
|
||||||
ofn.Flags |= OFN_HIDEREADONLY;
|
|
||||||
|
|
||||||
const std::wstring& filter = GetFilterString(params.accept_types);
|
|
||||||
if (!filter.empty()) {
|
|
||||||
ofn.lpstrFilter = filter.c_str();
|
|
||||||
// Indices into |lpstrFilter| start at 1.
|
|
||||||
ofn.nFilterIndex = *filter_index + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = !!GetOpenFileName(&ofn);
|
|
||||||
if (success) {
|
|
||||||
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
|
||||||
*path = base::FilePath(filename);
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunOpenMultiFileDialog(
|
|
||||||
const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
HWND owner,
|
|
||||||
int* filter_index,
|
|
||||||
std::vector<base::FilePath>* paths) {
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
|
|
||||||
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
|
||||||
// junk in release builds which can cause the Places Bar not to show up!
|
|
||||||
ZeroMemory(&ofn, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = owner;
|
|
||||||
|
|
||||||
std::unique_ptr<wchar_t[]> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]);
|
|
||||||
filename[0] = 0;
|
|
||||||
|
|
||||||
ofn.lpstrFile = filename.get();
|
|
||||||
ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
|
|
||||||
|
|
||||||
std::wstring directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!directory.empty())
|
|
||||||
ofn.lpstrInitialDir = directory.c_str();
|
|
||||||
|
|
||||||
std::wstring title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = base::UTF16ToWide(params.title);
|
|
||||||
} else {
|
|
||||||
title = base::UTF16ToWide(
|
|
||||||
l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
if (!title.empty())
|
|
||||||
ofn.lpstrTitle = title.c_str();
|
|
||||||
|
|
||||||
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
|
||||||
// without having to close Chrome first.
|
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
|
|
||||||
OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
|
|
||||||
if (params.hidereadonly)
|
|
||||||
ofn.Flags |= OFN_HIDEREADONLY;
|
|
||||||
|
|
||||||
const std::wstring& filter = GetFilterString(params.accept_types);
|
|
||||||
if (!filter.empty()) {
|
|
||||||
ofn.lpstrFilter = filter.c_str();
|
|
||||||
// Indices into |lpstrFilter| start at 1.
|
|
||||||
ofn.nFilterIndex = *filter_index + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = !!GetOpenFileName(&ofn);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
std::vector<base::FilePath> files;
|
|
||||||
const wchar_t* selection = ofn.lpstrFile;
|
|
||||||
while (*selection) { // Empty string indicates end of list.
|
|
||||||
files.push_back(base::FilePath(selection));
|
|
||||||
// Skip over filename and null-terminator.
|
|
||||||
selection += files.back().value().length() + 1;
|
|
||||||
}
|
|
||||||
if (files.empty()) {
|
|
||||||
success = false;
|
|
||||||
} else if (files.size() == 1) {
|
|
||||||
// When there is one file, it contains the path and filename.
|
|
||||||
paths->swap(files);
|
|
||||||
} else {
|
|
||||||
// Otherwise, the first string is the path, and the remainder are
|
|
||||||
// filenames.
|
|
||||||
std::vector<base::FilePath>::iterator path = files.begin();
|
|
||||||
for (std::vector<base::FilePath>::iterator file = path + 1;
|
|
||||||
file != files.end(); ++file) {
|
|
||||||
paths->push_back(path->Append(*file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The callback function for when the select folder dialog is opened.
|
|
||||||
int CALLBACK BrowseCallbackProc(HWND window,
|
|
||||||
UINT message,
|
|
||||||
LPARAM parameter,
|
|
||||||
LPARAM data) {
|
|
||||||
if (message == BFFM_INITIALIZED) {
|
|
||||||
// WParam is TRUE since passing a path.
|
|
||||||
// data lParam member of the BROWSEINFO structure.
|
|
||||||
SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunOpenFolderDialog(const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
HWND owner,
|
|
||||||
base::FilePath* path) {
|
|
||||||
wchar_t dir_buffer[MAX_PATH + 1] = {0};
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
BROWSEINFO browse_info = {0};
|
|
||||||
browse_info.hwndOwner = owner;
|
|
||||||
browse_info.pszDisplayName = dir_buffer;
|
|
||||||
browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
|
|
||||||
|
|
||||||
std::wstring title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = base::UTF16ToWide(params.title);
|
|
||||||
} else {
|
|
||||||
title = base::UTF16ToWide(
|
|
||||||
l10n_util::GetStringUTF16(IDS_SELECT_FOLDER_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
if (!title.empty())
|
|
||||||
browse_info.lpszTitle = title.c_str();
|
|
||||||
|
|
||||||
const std::wstring& file_path = params.default_file_name.value();
|
|
||||||
if (!file_path.empty()) {
|
|
||||||
// Highlight the current value.
|
|
||||||
browse_info.lParam = (LPARAM)file_path.c_str();
|
|
||||||
browse_info.lpfn = &BrowseCallbackProc;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPITEMIDLIST list = SHBrowseForFolder(&browse_info);
|
|
||||||
if (list) {
|
|
||||||
STRRET out_dir_buffer;
|
|
||||||
ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer));
|
|
||||||
out_dir_buffer.uType = STRRET_WSTR;
|
|
||||||
Microsoft::WRL::ComPtr<IShellFolder> shell_folder;
|
|
||||||
if (SHGetDesktopFolder(shell_folder.GetAddressOf()) == NOERROR) {
|
|
||||||
HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING,
|
|
||||||
&out_dir_buffer);
|
|
||||||
if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) {
|
|
||||||
*path = base::FilePath(out_dir_buffer.pOleStr);
|
|
||||||
CoTaskMemFree(out_dir_buffer.pOleStr);
|
|
||||||
result = true;
|
|
||||||
} else {
|
|
||||||
// Use old way if we don't get what we want.
|
|
||||||
wchar_t old_out_dir_buffer[MAX_PATH + 1];
|
|
||||||
if (SHGetPathFromIDList(list, old_out_dir_buffer)) {
|
|
||||||
*path = base::FilePath(old_out_dir_buffer);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CoTaskMemFree(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunSaveFileDialog(const CefFileDialogRunner::FileChooserParams& params,
|
|
||||||
HWND owner,
|
|
||||||
int* filter_index,
|
|
||||||
base::FilePath* path) {
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
|
|
||||||
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
|
||||||
// junk in release builds which can cause the Places Bar not to show up!
|
|
||||||
ZeroMemory(&ofn, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = owner;
|
|
||||||
|
|
||||||
wchar_t filename[MAX_PATH] = {0};
|
|
||||||
|
|
||||||
ofn.lpstrFile = filename;
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
|
|
||||||
std::wstring directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
|
||||||
std::size(filename));
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!directory.empty())
|
|
||||||
ofn.lpstrInitialDir = directory.c_str();
|
|
||||||
|
|
||||||
std::wstring title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = base::UTF16ToWide(params.title);
|
|
||||||
} else {
|
|
||||||
title =
|
|
||||||
base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
if (!title.empty())
|
|
||||||
ofn.lpstrTitle = title.c_str();
|
|
||||||
|
|
||||||
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
|
||||||
// without having to close Chrome first.
|
|
||||||
ofn.Flags =
|
|
||||||
OFN_EXPLORER | OFN_ENABLESIZING | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
|
|
||||||
if (params.hidereadonly)
|
|
||||||
ofn.Flags |= OFN_HIDEREADONLY;
|
|
||||||
if (params.overwriteprompt)
|
|
||||||
ofn.Flags |= OFN_OVERWRITEPROMPT;
|
|
||||||
|
|
||||||
const std::wstring& filter = GetFilterString(params.accept_types);
|
|
||||||
if (!filter.empty()) {
|
|
||||||
ofn.lpstrFilter = filter.c_str();
|
|
||||||
// Indices into |lpstrFilter| start at 1.
|
|
||||||
ofn.nFilterIndex = *filter_index + 1;
|
|
||||||
// If a filter is specified and the default file name is changed then append
|
|
||||||
// a file extension to the new name.
|
|
||||||
ofn.lpstrDefExt = L"";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = !!GetSaveFileName(&ofn);
|
|
||||||
if (success) {
|
|
||||||
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
|
||||||
*path = base::FilePath(filename);
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
CefFileDialogRunnerWin::CefFileDialogRunnerWin() {}
|
|
||||||
|
|
||||||
void CefFileDialogRunnerWin::Run(AlloyBrowserHostImpl* browser,
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) {
|
|
||||||
int filter_index = params.selected_accept_filter;
|
|
||||||
std::vector<base::FilePath> files;
|
|
||||||
|
|
||||||
HWND owner = browser->GetWindowHandle();
|
|
||||||
|
|
||||||
if (params.mode == blink::mojom::FileChooserParams::Mode::kOpen) {
|
|
||||||
base::FilePath file;
|
|
||||||
if (RunOpenFileDialog(params, owner, &filter_index, &file))
|
|
||||||
files.push_back(file);
|
|
||||||
} else if (params.mode ==
|
|
||||||
blink::mojom::FileChooserParams::Mode::kOpenMultiple) {
|
|
||||||
RunOpenMultiFileDialog(params, owner, &filter_index, &files);
|
|
||||||
} else if (params.mode ==
|
|
||||||
blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
|
||||||
base::FilePath file;
|
|
||||||
if (RunOpenFolderDialog(params, owner, &file))
|
|
||||||
files.push_back(file);
|
|
||||||
} else if (params.mode == blink::mojom::FileChooserParams::Mode::kSave) {
|
|
||||||
base::FilePath file;
|
|
||||||
if (RunSaveFileDialog(params, owner, &filter_index, &file))
|
|
||||||
files.push_back(file);
|
|
||||||
} else {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::move(callback).Run(filter_index, files);
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions 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_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "libcef/browser/file_dialog_runner.h"
|
|
||||||
|
|
||||||
class CefFileDialogRunnerWin : public CefFileDialogRunner {
|
|
||||||
public:
|
|
||||||
CefFileDialogRunnerWin();
|
|
||||||
|
|
||||||
// CefFileDialogRunner methods:
|
|
||||||
void Run(AlloyBrowserHostImpl* browser,
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
|
@ -194,11 +194,6 @@ CefEventHandle CefBrowserPlatformDelegateOsr::GetEventHandle(
|
|||||||
return native_delegate_->GetEventHandle(event);
|
return native_delegate_->GetEventHandle(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegateOsr::CreateFileDialogRunner() {
|
|
||||||
return native_delegate_->CreateFileDialogRunner();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegateOsr::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegateOsr::CreateJavaScriptDialogRunner() {
|
||||||
return native_delegate_->CreateJavaScriptDialogRunner();
|
return native_delegate_->CreateJavaScriptDialogRunner();
|
||||||
|
@ -49,7 +49,6 @@ class CefBrowserPlatformDelegateOsr
|
|||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const override;
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
||||||
override;
|
override;
|
||||||
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
@ -30,6 +30,33 @@ using content::BrowserThread;
|
|||||||
using printing::PageRanges;
|
using printing::PageRanges;
|
||||||
using printing::PrintSettings;
|
using printing::PrintSettings;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
printing::PrintingContextLinux::CreatePrintDialogFunctionPtr
|
||||||
|
g_default_create_print_dialog_func = nullptr;
|
||||||
|
printing::PrintingContextLinux::PdfPaperSizeFunctionPtr
|
||||||
|
g_default_pdf_paper_size_func = nullptr;
|
||||||
|
|
||||||
|
CefRefPtr<CefBrowserHostBase> GetBrowserForContext(
|
||||||
|
printing::PrintingContextLinux* context) {
|
||||||
|
return extensions::GetOwnerBrowserForGlobalId(
|
||||||
|
frame_util::MakeGlobalId(context->render_process_id(),
|
||||||
|
context->render_frame_id()),
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefPrintHandler> GetPrintHandlerForBrowser(
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser) {
|
||||||
|
if (browser) {
|
||||||
|
if (auto client = browser->GetClient()) {
|
||||||
|
return client->GetPrintHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class CefPrintDialogCallbackImpl : public CefPrintDialogCallback {
|
class CefPrintDialogCallbackImpl : public CefPrintDialogCallback {
|
||||||
public:
|
public:
|
||||||
explicit CefPrintDialogCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
|
explicit CefPrintDialogCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
|
||||||
@ -104,7 +131,30 @@ class CefPrintJobCallbackImpl : public CefPrintJobCallback {
|
|||||||
printing::PrintDialogGtkInterface* CefPrintDialogLinux::CreatePrintDialog(
|
printing::PrintDialogGtkInterface* CefPrintDialogLinux::CreatePrintDialog(
|
||||||
PrintingContextLinux* context) {
|
PrintingContextLinux* context) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
return new CefPrintDialogLinux(context);
|
|
||||||
|
printing::PrintDialogGtkInterface* interface = nullptr;
|
||||||
|
|
||||||
|
auto browser = GetBrowserForContext(context);
|
||||||
|
if (!browser) {
|
||||||
|
LOG(ERROR) << "No associated browser in CreatePrintDialog; using default "
|
||||||
|
"printing implementation.";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto handler = GetPrintHandlerForBrowser(browser);
|
||||||
|
if (!handler) {
|
||||||
|
if (g_default_create_print_dialog_func) {
|
||||||
|
interface = g_default_create_print_dialog_func(context);
|
||||||
|
DCHECK(interface);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
interface = new CefPrintDialogLinux(context, browser, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interface) {
|
||||||
|
LOG(ERROR) << "Null interface in CreatePrintDialog; printing will fail.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@ -114,27 +164,42 @@ gfx::Size CefPrintDialogLinux::GetPdfPaperSize(
|
|||||||
|
|
||||||
gfx::Size size;
|
gfx::Size size;
|
||||||
|
|
||||||
auto browser = extensions::GetOwnerBrowserForGlobalId(
|
auto browser = GetBrowserForContext(context);
|
||||||
frame_util::MakeGlobalId(context->render_process_id(),
|
if (!browser) {
|
||||||
context->render_frame_id()),
|
LOG(ERROR) << "No associated browser in GetPdfPaperSize; using default "
|
||||||
nullptr);
|
"printing implementation.";
|
||||||
DCHECK(browser);
|
}
|
||||||
if (browser && browser->GetClient()) {
|
|
||||||
if (auto handler = browser->GetClient()->GetPrintHandler()) {
|
auto handler = GetPrintHandlerForBrowser(browser);
|
||||||
const printing::PrintSettings& settings = context->settings();
|
if (!handler) {
|
||||||
CefSize cef_size = handler->GetPdfPaperSize(
|
if (g_default_pdf_paper_size_func) {
|
||||||
browser.get(), settings.device_units_per_inch());
|
size = g_default_pdf_paper_size_func(context);
|
||||||
size.SetSize(cef_size.width, cef_size.height);
|
DCHECK(!size.IsEmpty());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const printing::PrintSettings& settings = context->settings();
|
||||||
|
CefSize cef_size = handler->GetPdfPaperSize(
|
||||||
|
browser.get(), settings.device_units_per_inch());
|
||||||
|
size.SetSize(cef_size.width, cef_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size.IsEmpty()) {
|
if (size.IsEmpty()) {
|
||||||
LOG(ERROR) << "Empty size value returned in GetPdfPaperSize; "
|
LOG(ERROR) << "Empty size value returned in GetPdfPaperSize; PDF printing "
|
||||||
"PDF printing will fail.";
|
"will fail.";
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void CefPrintDialogLinux::SetDefaultPrintingContextFuncs(
|
||||||
|
printing::PrintingContextLinux::CreatePrintDialogFunctionPtr
|
||||||
|
create_print_dialog_func,
|
||||||
|
printing::PrintingContextLinux::PdfPaperSizeFunctionPtr
|
||||||
|
pdf_paper_size_func) {
|
||||||
|
g_default_create_print_dialog_func = create_print_dialog_func;
|
||||||
|
g_default_pdf_paper_size_func = pdf_paper_size_func;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void CefPrintDialogLinux::OnPrintStart(CefRefPtr<CefBrowserHostBase> browser) {
|
void CefPrintDialogLinux::OnPrintStart(CefRefPtr<CefBrowserHostBase> browser) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
@ -146,14 +211,13 @@ void CefPrintDialogLinux::OnPrintStart(CefRefPtr<CefBrowserHostBase> browser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context)
|
CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context,
|
||||||
: context_(context) {
|
CefRefPtr<CefBrowserHostBase> browser,
|
||||||
|
CefRefPtr<CefPrintHandler> handler)
|
||||||
|
: context_(context), browser_(browser), handler_(handler) {
|
||||||
DCHECK(context_);
|
DCHECK(context_);
|
||||||
browser_ = extensions::GetOwnerBrowserForGlobalId(
|
|
||||||
frame_util::MakeGlobalId(context_->render_process_id(),
|
|
||||||
context_->render_frame_id()),
|
|
||||||
nullptr);
|
|
||||||
DCHECK(browser_);
|
DCHECK(browser_);
|
||||||
|
DCHECK(handler_);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefPrintDialogLinux::~CefPrintDialogLinux() {
|
CefPrintDialogLinux::~CefPrintDialogLinux() {
|
||||||
@ -161,7 +225,7 @@ CefPrintDialogLinux::~CefPrintDialogLinux() {
|
|||||||
// object because the PrintJobWorker which owns |context_| may already have
|
// object because the PrintJobWorker which owns |context_| may already have
|
||||||
// been deleted.
|
// been deleted.
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
ReleaseHandler();
|
handler_->OnPrintReset(browser_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefPrintDialogLinux::UseDefaultSettings() {
|
void CefPrintDialogLinux::UseDefaultSettings() {
|
||||||
@ -179,12 +243,6 @@ void CefPrintDialogLinux::ShowDialog(
|
|||||||
PrintingContextLinux::PrintSettingsCallback callback) {
|
PrintingContextLinux::PrintSettingsCallback callback) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
SetHandler();
|
|
||||||
if (!handler_.get()) {
|
|
||||||
std::move(callback).Run(printing::mojom::ResultCode::kCanceled);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback_ = std::move(callback);
|
callback_ = std::move(callback);
|
||||||
|
|
||||||
CefRefPtr<CefPrintDialogCallbackImpl> callback_impl(
|
CefRefPtr<CefPrintDialogCallbackImpl> callback_impl(
|
||||||
@ -240,31 +298,11 @@ void CefPrintDialogLinux::ReleaseDialog() {
|
|||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefPrintDialogLinux::SetHandler() {
|
|
||||||
if (handler_.get())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (browser_ && browser_->GetClient()) {
|
|
||||||
handler_ = browser_->GetClient()->GetPrintHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefPrintDialogLinux::ReleaseHandler() {
|
|
||||||
if (handler_.get()) {
|
|
||||||
handler_->OnPrintReset(browser_.get());
|
|
||||||
handler_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefPrintDialogLinux::UpdateSettings(
|
bool CefPrintDialogLinux::UpdateSettings(
|
||||||
std::unique_ptr<PrintSettings> settings,
|
std::unique_ptr<PrintSettings> settings,
|
||||||
bool get_defaults) {
|
bool get_defaults) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
SetHandler();
|
|
||||||
if (!handler_.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CefRefPtr<CefPrintSettingsImpl> settings_impl(
|
CefRefPtr<CefPrintSettingsImpl> settings_impl(
|
||||||
new CefPrintSettingsImpl(std::move(settings), false));
|
new CefPrintSettingsImpl(std::move(settings), false));
|
||||||
handler_->OnPrintSettings(browser_.get(), settings_impl.get(), get_defaults);
|
handler_->OnPrintSettings(browser_.get(), settings_impl.get(), get_defaults);
|
||||||
|
@ -39,6 +39,13 @@ class CefPrintDialogLinux : public printing::PrintDialogGtkInterface,
|
|||||||
// Returns the paper size in device units.
|
// Returns the paper size in device units.
|
||||||
static gfx::Size GetPdfPaperSize(printing::PrintingContextLinux* context);
|
static gfx::Size GetPdfPaperSize(printing::PrintingContextLinux* context);
|
||||||
|
|
||||||
|
// Used for calling into the default GTK implementation.
|
||||||
|
static void SetDefaultPrintingContextFuncs(
|
||||||
|
printing::PrintingContextLinux::CreatePrintDialogFunctionPtr
|
||||||
|
create_print_dialog_func,
|
||||||
|
printing::PrintingContextLinux::PdfPaperSizeFunctionPtr
|
||||||
|
pdf_paper_size_func);
|
||||||
|
|
||||||
// Notify the client when printing has started.
|
// Notify the client when printing has started.
|
||||||
static void OnPrintStart(CefRefPtr<CefBrowserHostBase> browser);
|
static void OnPrintStart(CefRefPtr<CefBrowserHostBase> browser);
|
||||||
|
|
||||||
@ -65,12 +72,11 @@ class CefPrintDialogLinux : public printing::PrintDialogGtkInterface,
|
|||||||
friend class CefPrintDialogCallbackImpl;
|
friend class CefPrintDialogCallbackImpl;
|
||||||
friend class CefPrintJobCallbackImpl;
|
friend class CefPrintJobCallbackImpl;
|
||||||
|
|
||||||
explicit CefPrintDialogLinux(PrintingContextLinux* context);
|
CefPrintDialogLinux(PrintingContextLinux* context,
|
||||||
|
CefRefPtr<CefBrowserHostBase> browser,
|
||||||
|
CefRefPtr<CefPrintHandler> handler);
|
||||||
~CefPrintDialogLinux() override;
|
~CefPrintDialogLinux() override;
|
||||||
|
|
||||||
void SetHandler();
|
|
||||||
void ReleaseHandler();
|
|
||||||
|
|
||||||
bool UpdateSettings(std::unique_ptr<printing::PrintSettings> settings,
|
bool UpdateSettings(std::unique_ptr<printing::PrintSettings> settings,
|
||||||
bool get_defaults);
|
bool get_defaults);
|
||||||
|
|
||||||
@ -84,12 +90,12 @@ class CefPrintDialogLinux : public printing::PrintDialogGtkInterface,
|
|||||||
// Handles print job response.
|
// Handles print job response.
|
||||||
void OnJobCompleted();
|
void OnJobCompleted();
|
||||||
|
|
||||||
CefRefPtr<CefPrintHandler> handler_;
|
|
||||||
|
|
||||||
// Printing dialog callback.
|
// Printing dialog callback.
|
||||||
PrintingContextLinux::PrintSettingsCallback callback_;
|
PrintingContextLinux::PrintSettingsCallback callback_;
|
||||||
|
|
||||||
PrintingContextLinux* context_;
|
PrintingContextLinux* context_;
|
||||||
CefRefPtr<CefBrowserHostBase> browser_;
|
CefRefPtr<CefBrowserHostBase> browser_;
|
||||||
|
CefRefPtr<CefPrintHandler> handler_;
|
||||||
|
|
||||||
base::FilePath path_to_pdf_;
|
base::FilePath path_to_pdf_;
|
||||||
};
|
};
|
||||||
|
@ -257,11 +257,6 @@ CefEventHandle CefBrowserPlatformDelegateViews::GetEventHandle(
|
|||||||
return native_delegate_->GetEventHandle(event);
|
return native_delegate_->GetEventHandle(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CefFileDialogRunner>
|
|
||||||
CefBrowserPlatformDelegateViews::CreateFileDialogRunner() {
|
|
||||||
return native_delegate_->CreateFileDialogRunner();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner>
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
||||||
CefBrowserPlatformDelegateViews::CreateJavaScriptDialogRunner() {
|
CefBrowserPlatformDelegateViews::CreateJavaScriptDialogRunner() {
|
||||||
return native_delegate_->CreateJavaScriptDialogRunner();
|
return native_delegate_->CreateJavaScriptDialogRunner();
|
||||||
|
@ -60,7 +60,6 @@ class CefBrowserPlatformDelegateViews
|
|||||||
const content::NativeWebKeyboardEvent& event) override;
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const content::NativeWebKeyboardEvent& event) const override;
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
|
||||||
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
|
||||||
override;
|
override;
|
||||||
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=289bb032a65bfd1f35a97d93e14df1f5762a9394$
|
// $hash=65c260e354b6dc85bf121b60081eff450b043542$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
|
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
|
||||||
@ -318,7 +318,6 @@ browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
|||||||
const cef_string_t* title,
|
const cef_string_t* title,
|
||||||
const cef_string_t* default_file_path,
|
const cef_string_t* default_file_path,
|
||||||
cef_string_list_t accept_filters,
|
cef_string_list_t accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_run_file_dialog_callback_t* callback) {
|
cef_run_file_dialog_callback_t* callback) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -327,10 +326,6 @@ browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
|||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback);
|
DCHECK(callback);
|
||||||
if (!callback)
|
if (!callback)
|
||||||
@ -344,7 +339,7 @@ browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
|||||||
// Execute
|
// Execute
|
||||||
CefBrowserHostCppToC::Get(self)->RunFileDialog(
|
CefBrowserHostCppToC::Get(self)->RunFileDialog(
|
||||||
mode, CefString(title), CefString(default_file_path), accept_filtersList,
|
mode, CefString(title), CefString(default_file_path), accept_filtersList,
|
||||||
selected_accept_filter, CefRunFileDialogCallbackCToCpp::Wrap(callback));
|
CefRunFileDialogCallbackCToCpp::Wrap(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self,
|
void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self,
|
||||||
|
@ -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=639576c610ca3898809cdee6d19c45253e9ea4d2$
|
// $hash=3e2fc4cf108e13165c53ee3e8b10b483dbe5ff5e$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
|
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
|
||||||
@ -29,7 +29,6 @@ dialog_handler_on_file_dialog(struct _cef_dialog_handler_t* self,
|
|||||||
const cef_string_t* title,
|
const cef_string_t* title,
|
||||||
const cef_string_t* default_file_path,
|
const cef_string_t* default_file_path,
|
||||||
cef_string_list_t accept_filters,
|
cef_string_list_t accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_file_dialog_callback_t* callback) {
|
cef_file_dialog_callback_t* callback) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -42,10 +41,6 @@ dialog_handler_on_file_dialog(struct _cef_dialog_handler_t* self,
|
|||||||
DCHECK(browser);
|
DCHECK(browser);
|
||||||
if (!browser)
|
if (!browser)
|
||||||
return 0;
|
return 0;
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return 0;
|
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback);
|
DCHECK(callback);
|
||||||
if (!callback)
|
if (!callback)
|
||||||
@ -59,7 +54,7 @@ dialog_handler_on_file_dialog(struct _cef_dialog_handler_t* self,
|
|||||||
// Execute
|
// Execute
|
||||||
bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
|
bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
|
||||||
CefBrowserCToCpp::Wrap(browser), mode, CefString(title),
|
CefBrowserCToCpp::Wrap(browser), mode, CefString(title),
|
||||||
CefString(default_file_path), accept_filtersList, selected_accept_filter,
|
CefString(default_file_path), accept_filtersList,
|
||||||
CefFileDialogCallbackCToCpp::Wrap(callback));
|
CefFileDialogCallbackCToCpp::Wrap(callback));
|
||||||
|
|
||||||
// Return type: bool
|
// Return type: bool
|
||||||
|
@ -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=d334e579f498ad7727721dfe4e10ad810b81035a$
|
// $hash=1abedb0e8e7a0101d9ff3f4918f992f3c010d5a6$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
|
#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
|
||||||
@ -22,7 +22,6 @@ namespace {
|
|||||||
|
|
||||||
void CEF_CALLBACK
|
void CEF_CALLBACK
|
||||||
file_dialog_callback_cont(struct _cef_file_dialog_callback_t* self,
|
file_dialog_callback_cont(struct _cef_file_dialog_callback_t* self,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_string_list_t file_paths) {
|
cef_string_list_t file_paths) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -31,10 +30,6 @@ file_dialog_callback_cont(struct _cef_file_dialog_callback_t* self,
|
|||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Unverified params: file_paths
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
@ -42,8 +37,7 @@ file_dialog_callback_cont(struct _cef_file_dialog_callback_t* self,
|
|||||||
transfer_string_list_contents(file_paths, file_pathsList);
|
transfer_string_list_contents(file_paths, file_pathsList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefFileDialogCallbackCppToC::Get(self)->Continue(selected_accept_filter,
|
CefFileDialogCallbackCppToC::Get(self)->Continue(file_pathsList);
|
||||||
file_pathsList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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=2e6aa9015192a3704df073f7dad0c6fa3b05f76c$
|
// $hash=15fb714ee545d6ea2057ab82aec380dc25739199$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
|
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
|
||||||
@ -22,7 +22,6 @@ namespace {
|
|||||||
|
|
||||||
void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
|
void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
|
||||||
struct _cef_run_file_dialog_callback_t* self,
|
struct _cef_run_file_dialog_callback_t* self,
|
||||||
int selected_accept_filter,
|
|
||||||
cef_string_list_t file_paths) {
|
cef_string_list_t file_paths) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -31,10 +30,6 @@ void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
|
|||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Unverified params: file_paths
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
@ -43,7 +38,7 @@ void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
|
|||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
|
CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
|
||||||
selected_accept_filter, file_pathsList);
|
file_pathsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -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=2edab12ab1759213ab9a6b7620ea39a74291abc7$
|
// $hash=fa3208182bcdb9aab36096b3ce5ecdd35cb0a80f$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
|
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
|
||||||
@ -261,7 +261,6 @@ void CefBrowserHostCToCpp::RunFileDialog(
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -271,10 +270,6 @@ void CefBrowserHostCToCpp::RunFileDialog(
|
|||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get())
|
if (!callback.get())
|
||||||
@ -290,7 +285,6 @@ void CefBrowserHostCToCpp::RunFileDialog(
|
|||||||
// Execute
|
// Execute
|
||||||
_struct->run_file_dialog(_struct, mode, title.GetStruct(),
|
_struct->run_file_dialog(_struct, mode, title.GetStruct(),
|
||||||
default_file_path.GetStruct(), accept_filtersList,
|
default_file_path.GetStruct(), accept_filtersList,
|
||||||
selected_accept_filter,
|
|
||||||
CefRunFileDialogCallbackCppToC::Wrap(callback));
|
CefRunFileDialogCallbackCppToC::Wrap(callback));
|
||||||
|
|
||||||
// Restore param:accept_filters; type: string_vec_byref_const
|
// Restore param:accept_filters; type: string_vec_byref_const
|
||||||
|
@ -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=6de4205143b6855e7ccf54da14a0494db0b4aaa3$
|
// $hash=e82e7bf06a027262268172fd74254a8af087e528$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
|
||||||
@ -52,7 +52,6 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
||||||
void StartDownload(const CefString& url) override;
|
void StartDownload(const CefString& url) override;
|
||||||
void DownloadImage(const CefString& image_url,
|
void DownloadImage(const CefString& image_url,
|
||||||
|
@ -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=cac933371fc47c864230d4537ef1da76cd7e4d8e$
|
// $hash=336c57e3c57a1a5bf8fa4a39aee8f204788ccddb$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
|
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
|
||||||
@ -27,7 +27,6 @@ bool CefDialogHandlerCToCpp::OnFileDialog(
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -41,10 +40,6 @@ bool CefDialogHandlerCToCpp::OnFileDialog(
|
|||||||
DCHECK(browser.get());
|
DCHECK(browser.get());
|
||||||
if (!browser.get())
|
if (!browser.get())
|
||||||
return false;
|
return false;
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
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())
|
||||||
@ -60,7 +55,7 @@ bool CefDialogHandlerCToCpp::OnFileDialog(
|
|||||||
// Execute
|
// Execute
|
||||||
int _retval = _struct->on_file_dialog(
|
int _retval = _struct->on_file_dialog(
|
||||||
_struct, CefBrowserCppToC::Wrap(browser), mode, title.GetStruct(),
|
_struct, CefBrowserCppToC::Wrap(browser), mode, title.GetStruct(),
|
||||||
default_file_path.GetStruct(), accept_filtersList, selected_accept_filter,
|
default_file_path.GetStruct(), accept_filtersList,
|
||||||
CefFileDialogCallbackCppToC::Wrap(callback));
|
CefFileDialogCallbackCppToC::Wrap(callback));
|
||||||
|
|
||||||
// Restore param:accept_filters; type: string_vec_byref_const
|
// Restore param:accept_filters; type: string_vec_byref_const
|
||||||
|
@ -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=4c07a40d3bd171adf3ae3cc4aa935bc7eca4aa5e$
|
// $hash=1577adae508ad046bb2c7786f040ccc599087b8d$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_
|
||||||
@ -41,7 +41,6 @@ class CefDialogHandlerCToCpp
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) override;
|
CefRefPtr<CefFileDialogCallback> callback) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=8fecb808fb6a84d630d1e8c5380a5ffd900b3654$
|
// $hash=9fb143d4df823ed6a7dfca295ce4ca2b5756df9c$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
|
#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
|
||||||
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
NO_SANITIZE("cfi-icall")
|
NO_SANITIZE("cfi-icall")
|
||||||
void CefFileDialogCallbackCToCpp::Continue(
|
void CefFileDialogCallbackCToCpp::Continue(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) {
|
const std::vector<CefString>& file_paths) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -30,10 +29,6 @@ void CefFileDialogCallbackCToCpp::Continue(
|
|||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Unverified params: file_paths
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
@ -43,7 +38,7 @@ void CefFileDialogCallbackCToCpp::Continue(
|
|||||||
transfer_string_list_contents(file_paths, file_pathsList);
|
transfer_string_list_contents(file_paths, file_pathsList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
_struct->cont(_struct, selected_accept_filter, file_pathsList);
|
_struct->cont(_struct, file_pathsList);
|
||||||
|
|
||||||
// Restore param:file_paths; type: string_vec_byref_const
|
// Restore param:file_paths; type: string_vec_byref_const
|
||||||
if (file_pathsList)
|
if (file_pathsList)
|
||||||
|
@ -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=d84ac439b3372160aa3886b28b3ff81e49f05a6d$
|
// $hash=acb14970579704b71425d23b2bb7468f782a1e17$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
||||||
@ -36,8 +36,7 @@ class CefFileDialogCallbackCToCpp
|
|||||||
virtual ~CefFileDialogCallbackCToCpp();
|
virtual ~CefFileDialogCallbackCToCpp();
|
||||||
|
|
||||||
// CefFileDialogCallback methods.
|
// CefFileDialogCallback methods.
|
||||||
void Continue(int selected_accept_filter,
|
void Continue(const std::vector<CefString>& file_paths) override;
|
||||||
const std::vector<CefString>& file_paths) override;
|
|
||||||
void Cancel() override;
|
void Cancel() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// implementations. See the translator.README.txt file in the tools directory
|
// implementations. See the translator.README.txt file in the tools directory
|
||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
// $hash=cb29585261ed25ddd2ee1b4b5c890565e72e5d22$
|
// $hash=ef632f8846499c0605300240a2ec7240a1750ce2$
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
|
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
|
||||||
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
NO_SANITIZE("cfi-icall")
|
NO_SANITIZE("cfi-icall")
|
||||||
void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) {
|
const std::vector<CefString>& file_paths) {
|
||||||
shutdown_checker::AssertNotShutdown();
|
shutdown_checker::AssertNotShutdown();
|
||||||
|
|
||||||
@ -30,10 +29,6 @@ void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
|||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
// Verify param: selected_accept_filter; type: simple_byval
|
|
||||||
DCHECK_GE(selected_accept_filter, 0);
|
|
||||||
if (selected_accept_filter < 0)
|
|
||||||
return;
|
|
||||||
// Unverified params: file_paths
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
@ -43,8 +38,7 @@ void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
|||||||
transfer_string_list_contents(file_paths, file_pathsList);
|
transfer_string_list_contents(file_paths, file_pathsList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
_struct->on_file_dialog_dismissed(_struct, selected_accept_filter,
|
_struct->on_file_dialog_dismissed(_struct, file_pathsList);
|
||||||
file_pathsList);
|
|
||||||
|
|
||||||
// Restore param:file_paths; type: string_vec_byref_const
|
// Restore param:file_paths; type: string_vec_byref_const
|
||||||
if (file_pathsList)
|
if (file_pathsList)
|
||||||
|
@ -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=63d2d1da715395296899acc4ed165cf7dae4d78c$
|
// $hash=12c1546549e1b0d29beb91241361581f3e3da67f$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
||||||
@ -38,8 +38,7 @@ class CefRunFileDialogCallbackCToCpp
|
|||||||
virtual ~CefRunFileDialogCallbackCToCpp();
|
virtual ~CefRunFileDialogCallbackCToCpp();
|
||||||
|
|
||||||
// CefRunFileDialogCallback methods.
|
// CefRunFileDialogCallback methods.
|
||||||
void OnFileDialogDismissed(int selected_accept_filter,
|
void OnFileDialogDismissed(const std::vector<CefString>& file_paths) override;
|
||||||
const std::vector<CefString>& file_paths) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
#endif // CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
|
||||||
|
@ -202,6 +202,10 @@ patches = [
|
|||||||
{
|
{
|
||||||
# Changes to support the Chrome runtime in CEF.
|
# Changes to support the Chrome runtime in CEF.
|
||||||
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
||||||
|
#
|
||||||
|
# Fix fatal error: 'components/printing/common/print.mojom.h' file not found
|
||||||
|
# From chrome/browser/ui/browser_commands.cc via
|
||||||
|
# chrome/browser/printing/print_view_manager_common.h
|
||||||
'name': 'chrome_browser_browser',
|
'name': 'chrome_browser_browser',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -217,6 +221,14 @@ patches = [
|
|||||||
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
||||||
'name': 'chrome_browser_context_menus',
|
'name': 'chrome_browser_context_menus',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
# Support use of chrome dialogs with CEF runtimes.
|
||||||
|
# - Adds support for FileSelectHelper and SelectFileDialog interception.
|
||||||
|
# - Adds additional type filters for dialogs created via FileSelectHelper.
|
||||||
|
# - Adds support for chaining PrintingContextLinux callbacks.
|
||||||
|
# https://bitbucket.org/chromiumembedded/cef/issues/3314
|
||||||
|
'name': 'chrome_browser_dialogs',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
# chrome: Support override of ChromeMimeHandlerViewGuestDelegate.
|
# chrome: Support override of ChromeMimeHandlerViewGuestDelegate.
|
||||||
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
||||||
@ -243,15 +255,6 @@ patches = [
|
|||||||
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
# https://bitbucket.org/chromiumembedded/cef/issues/2969
|
||||||
'name': 'chrome_browser_profile_menu',
|
'name': 'chrome_browser_profile_menu',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
# Show the CEF Save As dialog.
|
|
||||||
# https://bitbucket.org/chromiumembedded/cef/issues/2613
|
|
||||||
#
|
|
||||||
# Fix fatal error: 'components/printing/common/print.mojom.h' file not found
|
|
||||||
# From chrome/browser/ui/browser_commands.cc via
|
|
||||||
# chrome/browser/printing/print_view_manager_common.h
|
|
||||||
'name': 'chrome_browser_net_export',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
# Support override of the User-Agent product component when NetworkService
|
# Support override of the User-Agent product component when NetworkService
|
||||||
# is enabled.
|
# is enabled.
|
||||||
|
@ -12,6 +12,45 @@ index 9e534ff1683f1..de406f5879be0 100644
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
|
||||||
|
index 936021a313995..2dd2554f8a7c5 100644
|
||||||
|
--- chrome/browser/ui/BUILD.gn
|
||||||
|
+++ chrome/browser/ui/BUILD.gn
|
||||||
|
@@ -10,6 +10,7 @@ import("//build/config/features.gni")
|
||||||
|
import("//build/config/linux/gtk/gtk.gni")
|
||||||
|
import("//build/config/ozone.gni")
|
||||||
|
import("//build/config/ui.gni")
|
||||||
|
+import("//cef/libcef/features/features.gni")
|
||||||
|
import("//chrome/browser/buildflags.gni")
|
||||||
|
import("//chrome/common/features.gni")
|
||||||
|
import("//chromeos/assistant/assistant.gni")
|
||||||
|
@@ -353,6 +354,10 @@ static_library("ui") {
|
||||||
|
"//build/config/compiler:wexit_time_destructors",
|
||||||
|
]
|
||||||
|
|
||||||
|
+ if (enable_cef) {
|
||||||
|
+ configs += [ "//cef/libcef/features:config" ]
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
# Since browser and browser_ui actually depend on each other,
|
||||||
|
# we must omit the dependency from browser_ui to browser.
|
||||||
|
# However, this means browser_ui and browser should more or less
|
||||||
|
@@ -375,6 +380,7 @@ static_library("ui") {
|
||||||
|
"//build:branding_buildflags",
|
||||||
|
"//build:chromeos_buildflags",
|
||||||
|
"//cc/paint",
|
||||||
|
+ "//cef/libcef/features",
|
||||||
|
"//chrome:extra_resources",
|
||||||
|
"//chrome:resources",
|
||||||
|
"//chrome:strings",
|
||||||
|
@@ -5301,6 +5307,7 @@ static_library("ui") {
|
||||||
|
if (enable_basic_printing) {
|
||||||
|
deps += [
|
||||||
|
"//components/printing/browser",
|
||||||
|
+ "//components/printing/common:mojo_interfaces",
|
||||||
|
"//printing",
|
||||||
|
]
|
||||||
|
}
|
||||||
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
||||||
index 3284c6c6353cc..6694f9000c14a 100644
|
index 3284c6c6353cc..6694f9000c14a 100644
|
||||||
--- chrome/browser/ui/browser.cc
|
--- chrome/browser/ui/browser.cc
|
||||||
|
400
patch/patches/chrome_browser_dialogs.patch
Normal file
400
patch/patches/chrome_browser_dialogs.patch
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
diff --git chrome/browser/file_select_helper.cc chrome/browser/file_select_helper.cc
|
||||||
|
index 8792cc3a5d40e..8807feaf6063c 100644
|
||||||
|
--- chrome/browser/file_select_helper.cc
|
||||||
|
+++ chrome/browser/file_select_helper.cc
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
#include "base/threading/hang_watcher.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "build/chromeos_buildflags.h"
|
||||||
|
+#include "cef/libcef/features/runtime.h"
|
||||||
|
#include "chrome/browser/browser_process.h"
|
||||||
|
#include "chrome/browser/enterprise/connectors/common.h"
|
||||||
|
#include "chrome/browser/platform_util.h"
|
||||||
|
@@ -254,6 +255,13 @@ void FileSelectHelper::OnListFile(
|
||||||
|
void FileSelectHelper::LaunchConfirmationDialog(
|
||||||
|
const base::FilePath& path,
|
||||||
|
std::vector<ui::SelectedFileInfo> selected_files) {
|
||||||
|
+ if (cef::IsAlloyRuntimeEnabled() || run_from_cef_) {
|
||||||
|
+ // Don't show the upload confirmation dialog with the Alloy runtime, or
|
||||||
|
+ // when triggered via CEF (initially or recursively).
|
||||||
|
+ ConvertToFileChooserFileInfoList(selected_files);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ShowFolderUploadConfirmationDialog(
|
||||||
|
path,
|
||||||
|
base::BindOnce(&FileSelectHelper::ConvertToFileChooserFileInfoList, this),
|
||||||
|
@@ -450,7 +458,8 @@ void FileSelectHelper::DontAbortOnMissingWebContentsForTesting() {
|
||||||
|
|
||||||
|
std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
|
||||||
|
FileSelectHelper::GetFileTypesFromAcceptType(
|
||||||
|
- const std::vector<std::u16string>& accept_types) {
|
||||||
|
+ const std::vector<std::u16string>& accept_types,
|
||||||
|
+ bool run_from_cef) {
|
||||||
|
std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> base_file_type(
|
||||||
|
new ui::SelectFileDialog::FileTypeInfo());
|
||||||
|
if (accept_types.empty())
|
||||||
|
@@ -464,17 +473,24 @@ FileSelectHelper::GetFileTypesFromAcceptType(
|
||||||
|
std::vector<base::FilePath::StringType>* extensions =
|
||||||
|
&file_type->extensions.back();
|
||||||
|
|
||||||
|
+ // Create individual filters for each accept type.
|
||||||
|
+ std::vector<std::vector<base::FilePath::StringType>> all_extensions;
|
||||||
|
+ std::vector<std::u16string> all_overrides;
|
||||||
|
+
|
||||||
|
// Find the corresponding extensions.
|
||||||
|
int valid_type_count = 0;
|
||||||
|
int description_id = 0;
|
||||||
|
for (const auto& accept_type : accept_types) {
|
||||||
|
+ std::vector<base::FilePath::StringType> current_extensions;
|
||||||
|
+ description_id = 0;
|
||||||
|
+
|
||||||
|
size_t old_extension_size = extensions->size();
|
||||||
|
if (accept_type[0] == '.') {
|
||||||
|
// If the type starts with a period it is assumed to be a file extension
|
||||||
|
// so we just have to add it to the list.
|
||||||
|
base::FilePath::StringType ext =
|
||||||
|
base::FilePath::FromUTF16Unsafe(accept_type).value();
|
||||||
|
- extensions->push_back(ext.substr(1));
|
||||||
|
+ current_extensions.push_back(ext.substr(1));
|
||||||
|
} else {
|
||||||
|
if (!base::IsStringASCII(accept_type))
|
||||||
|
continue;
|
||||||
|
@@ -485,10 +501,18 @@ FileSelectHelper::GetFileTypesFromAcceptType(
|
||||||
|
description_id = IDS_AUDIO_FILES;
|
||||||
|
else if (ascii_type == "video/*")
|
||||||
|
description_id = IDS_VIDEO_FILES;
|
||||||
|
-
|
||||||
|
- net::GetExtensionsForMimeType(ascii_type, extensions);
|
||||||
|
+ net::GetExtensionsForMimeType(ascii_type, ¤t_extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (!current_extensions.empty()) {
|
||||||
|
+ all_extensions.push_back(current_extensions);
|
||||||
|
+ all_overrides.push_back(description_id != 0 ?
|
||||||
|
+ l10n_util::GetStringUTF16(description_id) :
|
||||||
|
+ std::u16string());
|
||||||
|
+
|
||||||
|
+ extensions->insert(extensions->end(), current_extensions.begin(),
|
||||||
|
+ current_extensions.end());
|
||||||
|
+ }
|
||||||
|
if (extensions->size() > old_extension_size)
|
||||||
|
valid_type_count++;
|
||||||
|
}
|
||||||
|
@@ -513,6 +537,15 @@ FileSelectHelper::GetFileTypesFromAcceptType(
|
||||||
|
l10n_util::GetStringUTF16(description_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (run_from_cef && all_extensions.size() > 1) {
|
||||||
|
+ // Insert filters for the specific accept types at the beginning.
|
||||||
|
+ file_type->extensions.insert(file_type->extensions.begin(),
|
||||||
|
+ all_extensions.begin(), all_extensions.end());
|
||||||
|
+ file_type->extension_description_overrides.insert(
|
||||||
|
+ file_type->extension_description_overrides.begin(),
|
||||||
|
+ all_overrides.begin(), all_overrides.end());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return file_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -520,7 +553,8 @@ FileSelectHelper::GetFileTypesFromAcceptType(
|
||||||
|
void FileSelectHelper::RunFileChooser(
|
||||||
|
content::RenderFrameHost* render_frame_host,
|
||||||
|
scoped_refptr<content::FileSelectListener> listener,
|
||||||
|
- const FileChooserParams& params) {
|
||||||
|
+ const FileChooserParams& params,
|
||||||
|
+ bool run_from_cef) {
|
||||||
|
Profile* profile = Profile::FromBrowserContext(
|
||||||
|
render_frame_host->GetProcess()->GetBrowserContext());
|
||||||
|
|
||||||
|
@@ -539,6 +573,7 @@ void FileSelectHelper::RunFileChooser(
|
||||||
|
// message.
|
||||||
|
scoped_refptr<FileSelectHelper> file_select_helper(
|
||||||
|
new FileSelectHelper(profile));
|
||||||
|
+ file_select_helper->run_from_cef_ = run_from_cef;
|
||||||
|
file_select_helper->RunFileChooser(render_frame_host, std::move(listener),
|
||||||
|
params.Clone());
|
||||||
|
}
|
||||||
|
@@ -592,7 +627,8 @@ void FileSelectHelper::RunFileChooser(
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelectHelper::GetFileTypesInThreadPool(FileChooserParamsPtr params) {
|
||||||
|
- select_file_types_ = GetFileTypesFromAcceptType(params->accept_types);
|
||||||
|
+ select_file_types_ = GetFileTypesFromAcceptType(params->accept_types,
|
||||||
|
+ run_from_cef_);
|
||||||
|
select_file_types_->allowed_paths =
|
||||||
|
params->need_local_path ? ui::SelectFileDialog::FileTypeInfo::NATIVE_PATH
|
||||||
|
: ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
|
||||||
|
diff --git chrome/browser/file_select_helper.h chrome/browser/file_select_helper.h
|
||||||
|
index f9d1f31b36357..122e1ce9fa962 100644
|
||||||
|
--- chrome/browser/file_select_helper.h
|
||||||
|
+++ chrome/browser/file_select_helper.h
|
||||||
|
@@ -59,7 +59,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
|
||||||
|
static void RunFileChooser(
|
||||||
|
content::RenderFrameHost* render_frame_host,
|
||||||
|
scoped_refptr<content::FileSelectListener> listener,
|
||||||
|
- const blink::mojom::FileChooserParams& params);
|
||||||
|
+ const blink::mojom::FileChooserParams& params,
|
||||||
|
+ bool run_from_cef = false);
|
||||||
|
|
||||||
|
// Enumerates all the files in directory.
|
||||||
|
static void EnumerateDirectory(
|
||||||
|
@@ -255,7 +256,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
|
||||||
|
// |accept_types| contains only valid lowercased MIME types or file extensions
|
||||||
|
// beginning with a period (.).
|
||||||
|
static std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
|
||||||
|
- GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types);
|
||||||
|
+ GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types,
|
||||||
|
+ bool run_from_cef);
|
||||||
|
|
||||||
|
// Check the accept type is valid. It is expected to be all lower case with
|
||||||
|
// no whitespace.
|
||||||
|
@@ -319,6 +321,9 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
|
||||||
|
|
||||||
|
// Set to false in unit tests since there is no WebContents.
|
||||||
|
bool abort_on_missing_web_contents_in_tests_ = true;
|
||||||
|
+
|
||||||
|
+ // Set to true if this dialog was triggered via CEF.
|
||||||
|
+ bool run_from_cef_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_FILE_SELECT_HELPER_H_
|
||||||
|
diff --git chrome/browser/ui/chrome_select_file_policy.h chrome/browser/ui/chrome_select_file_policy.h
|
||||||
|
index 2cf473c35b67a..e3552bd0f17d4 100644
|
||||||
|
--- chrome/browser/ui/chrome_select_file_policy.h
|
||||||
|
+++ chrome/browser/ui/chrome_select_file_policy.h
|
||||||
|
@@ -30,6 +30,8 @@ class ChromeSelectFilePolicy : public ui::SelectFilePolicy {
|
||||||
|
// Returns true if local state allows showing file pickers.
|
||||||
|
static bool FileSelectDialogsAllowed();
|
||||||
|
|
||||||
|
+ content::WebContents* source_contents() const { return source_contents_; }
|
||||||
|
+
|
||||||
|
private:
|
||||||
|
raw_ptr<content::WebContents> source_contents_;
|
||||||
|
};
|
||||||
|
diff --git printing/printing_context_linux.cc printing/printing_context_linux.cc
|
||||||
|
index 204cec8311bec..b2d7e16614e15 100644
|
||||||
|
--- printing/printing_context_linux.cc
|
||||||
|
+++ printing/printing_context_linux.cc
|
||||||
|
@@ -54,20 +54,23 @@ PrintingContextLinux::~PrintingContextLinux() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
-void PrintingContextLinux::SetCreatePrintDialogFunction(
|
||||||
|
- PrintDialogGtkInterface* (*create_dialog_func)(
|
||||||
|
- PrintingContextLinux* context)) {
|
||||||
|
+PrintingContextLinux::CreatePrintDialogFunctionPtr
|
||||||
|
+PrintingContextLinux::SetCreatePrintDialogFunction(
|
||||||
|
+ CreatePrintDialogFunctionPtr create_dialog_func) {
|
||||||
|
DCHECK(create_dialog_func);
|
||||||
|
- DCHECK(!create_dialog_func_);
|
||||||
|
+ auto old_func = create_dialog_func_;
|
||||||
|
create_dialog_func_ = create_dialog_func;
|
||||||
|
+ return old_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
-void PrintingContextLinux::SetPdfPaperSizeFunction(
|
||||||
|
- gfx::Size (*get_pdf_paper_size)(PrintingContextLinux* context)) {
|
||||||
|
+PrintingContextLinux::PdfPaperSizeFunctionPtr
|
||||||
|
+PrintingContextLinux::SetPdfPaperSizeFunction(
|
||||||
|
+ PdfPaperSizeFunctionPtr get_pdf_paper_size) {
|
||||||
|
DCHECK(get_pdf_paper_size);
|
||||||
|
- DCHECK(!get_pdf_paper_size_);
|
||||||
|
+ auto old_func = get_pdf_paper_size_;
|
||||||
|
get_pdf_paper_size_ = get_pdf_paper_size;
|
||||||
|
+ return old_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintingContextLinux::AskUserForSettings(int max_pages,
|
||||||
|
diff --git printing/printing_context_linux.h printing/printing_context_linux.h
|
||||||
|
index 653170ba60e83..677df89f93e8d 100644
|
||||||
|
--- printing/printing_context_linux.h
|
||||||
|
+++ printing/printing_context_linux.h
|
||||||
|
@@ -25,12 +25,17 @@ class COMPONENT_EXPORT(PRINTING) PrintingContextLinux : public PrintingContext {
|
||||||
|
~PrintingContextLinux() override;
|
||||||
|
|
||||||
|
// Sets the function that creates the print dialog.
|
||||||
|
- static void SetCreatePrintDialogFunction(PrintDialogGtkInterface* (
|
||||||
|
- *create_dialog_func)(PrintingContextLinux* context));
|
||||||
|
+ // Returns the old function, if any.
|
||||||
|
+ using CreatePrintDialogFunctionPtr =
|
||||||
|
+ PrintDialogGtkInterface* (*)(PrintingContextLinux* context);
|
||||||
|
+ static CreatePrintDialogFunctionPtr SetCreatePrintDialogFunction(
|
||||||
|
+ CreatePrintDialogFunctionPtr);
|
||||||
|
|
||||||
|
// Sets the function that returns pdf paper size through the native API.
|
||||||
|
- static void SetPdfPaperSizeFunction(
|
||||||
|
- gfx::Size (*get_pdf_paper_size)(PrintingContextLinux* context));
|
||||||
|
+ // Returns the old function, if any.
|
||||||
|
+ using PdfPaperSizeFunctionPtr = gfx::Size (*)(PrintingContextLinux* context);
|
||||||
|
+ static PdfPaperSizeFunctionPtr SetPdfPaperSizeFunction(
|
||||||
|
+ PdfPaperSizeFunctionPtr);
|
||||||
|
|
||||||
|
// Initializes with predefined settings.
|
||||||
|
void InitWithSettings(std::unique_ptr<PrintSettings> settings);
|
||||||
|
diff --git ui/shell_dialogs/execute_select_file_win.cc ui/shell_dialogs/execute_select_file_win.cc
|
||||||
|
index 063d4c7c96cba..24bd0533af65b 100644
|
||||||
|
--- ui/shell_dialogs/execute_select_file_win.cc
|
||||||
|
+++ ui/shell_dialogs/execute_select_file_win.cc
|
||||||
|
@@ -289,9 +289,7 @@ bool ExecuteSelectSingleFile(HWND owner,
|
||||||
|
const std::vector<FileFilterSpec>& filter,
|
||||||
|
int* filter_index,
|
||||||
|
std::vector<base::FilePath>* paths) {
|
||||||
|
- // Note: The title is not passed down for historical reasons.
|
||||||
|
- // TODO(pmonette): Figure out if it's a worthwhile improvement.
|
||||||
|
- return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
|
||||||
|
+ return RunOpenFileDialog(owner, title, std::u16string(),
|
||||||
|
default_path, filter, 0, filter_index, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -303,14 +301,13 @@ bool ExecuteSelectMultipleFile(HWND owner,
|
||||||
|
std::vector<base::FilePath>* paths) {
|
||||||
|
DWORD dialog_options = FOS_ALLOWMULTISELECT;
|
||||||
|
|
||||||
|
- // Note: The title is not passed down for historical reasons.
|
||||||
|
- // TODO(pmonette): Figure out if it's a worthwhile improvement.
|
||||||
|
- return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
|
||||||
|
+ return RunOpenFileDialog(owner, title, std::u16string(),
|
||||||
|
default_path, filter, dialog_options, filter_index,
|
||||||
|
paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExecuteSaveFile(HWND owner,
|
||||||
|
+ const std::u16string& title,
|
||||||
|
const base::FilePath& default_path,
|
||||||
|
const std::vector<FileFilterSpec>& filter,
|
||||||
|
const std::wstring& def_ext,
|
||||||
|
@@ -323,9 +320,7 @@ bool ExecuteSaveFile(HWND owner,
|
||||||
|
|
||||||
|
DWORD dialog_options = FOS_OVERWRITEPROMPT;
|
||||||
|
|
||||||
|
- // Note: The title is not passed down for historical reasons.
|
||||||
|
- // TODO(pmonette): Figure out if it's a worthwhile improvement.
|
||||||
|
- return RunSaveFileDialog(owner, std::u16string(), default_path, filter,
|
||||||
|
+ return RunSaveFileDialog(owner, title, default_path, filter,
|
||||||
|
dialog_options, def_ext, filter_index, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -390,7 +385,7 @@ void ExecuteSelectFile(
|
||||||
|
break;
|
||||||
|
case SelectFileDialog::SELECT_SAVEAS_FILE: {
|
||||||
|
base::FilePath path;
|
||||||
|
- if (ExecuteSaveFile(owner, default_path, filter, default_extension,
|
||||||
|
+ if (ExecuteSaveFile(owner, title, default_path, filter, default_extension,
|
||||||
|
&file_type_index, &path)) {
|
||||||
|
paths.push_back(std::move(path));
|
||||||
|
}
|
||||||
|
diff --git ui/shell_dialogs/select_file_dialog.cc ui/shell_dialogs/select_file_dialog.cc
|
||||||
|
index a622d465ab9e9..b5c11c3117738 100644
|
||||||
|
--- ui/shell_dialogs/select_file_dialog.cc
|
||||||
|
+++ ui/shell_dialogs/select_file_dialog.cc
|
||||||
|
@@ -64,8 +64,10 @@ void SelectFileDialog::SetFactory(ui::SelectFileDialogFactory* factory) {
|
||||||
|
// static
|
||||||
|
scoped_refptr<SelectFileDialog> SelectFileDialog::Create(
|
||||||
|
Listener* listener,
|
||||||
|
- std::unique_ptr<ui::SelectFilePolicy> policy) {
|
||||||
|
- if (dialog_factory_)
|
||||||
|
+ std::unique_ptr<ui::SelectFilePolicy> policy,
|
||||||
|
+ bool run_from_cef) {
|
||||||
|
+ // Avoid reentrancy of the CEF factory.
|
||||||
|
+ if (dialog_factory_ && (!run_from_cef || !dialog_factory_->IsCefFactory()))
|
||||||
|
return dialog_factory_->Create(listener, std::move(policy));
|
||||||
|
return CreateSelectFileDialog(listener, std::move(policy));
|
||||||
|
}
|
||||||
|
diff --git ui/shell_dialogs/select_file_dialog.h ui/shell_dialogs/select_file_dialog.h
|
||||||
|
index 8a417fc43a7e4..6d7b065b5b192 100644
|
||||||
|
--- ui/shell_dialogs/select_file_dialog.h
|
||||||
|
+++ ui/shell_dialogs/select_file_dialog.h
|
||||||
|
@@ -111,7 +111,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
|
||||||
|
// is refcounted and uses a background thread.
|
||||||
|
static scoped_refptr<SelectFileDialog> Create(
|
||||||
|
Listener* listener,
|
||||||
|
- std::unique_ptr<SelectFilePolicy> policy);
|
||||||
|
+ std::unique_ptr<SelectFilePolicy> policy,
|
||||||
|
+ bool run_from_cef = false);
|
||||||
|
|
||||||
|
SelectFileDialog(const SelectFileDialog&) = delete;
|
||||||
|
SelectFileDialog& operator=(const SelectFileDialog&) = delete;
|
||||||
|
@@ -205,6 +206,19 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
|
||||||
|
void* params);
|
||||||
|
bool HasMultipleFileTypeChoices();
|
||||||
|
|
||||||
|
+ // Match the types used by CefWindowHandle.
|
||||||
|
+#if BUILDFLAG(IS_MAC)
|
||||||
|
+ using WidgetType = void*;
|
||||||
|
+ static constexpr WidgetType kNullWidget = nullptr;
|
||||||
|
+#else
|
||||||
|
+ using WidgetType = gfx::AcceleratedWidget;
|
||||||
|
+ static constexpr WidgetType kNullWidget = gfx::kNullAcceleratedWidget;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ void set_owning_widget(WidgetType widget) {
|
||||||
|
+ owning_widget_ = widget;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
protected:
|
||||||
|
friend class base::RefCountedThreadSafe<SelectFileDialog>;
|
||||||
|
|
||||||
|
@@ -229,6 +243,11 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
|
||||||
|
// The listener to be notified of selection completion.
|
||||||
|
raw_ptr<Listener> listener_;
|
||||||
|
|
||||||
|
+ std::unique_ptr<SelectFilePolicy> select_file_policy_;
|
||||||
|
+
|
||||||
|
+ // Support override of the |owning_window| value.
|
||||||
|
+ WidgetType owning_widget_ = kNullWidget;
|
||||||
|
+
|
||||||
|
private:
|
||||||
|
// Tests if the file selection dialog can be displayed by
|
||||||
|
// testing if the AllowFileSelectionDialogs-Policy is
|
||||||
|
@@ -241,8 +260,6 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
|
||||||
|
|
||||||
|
// Returns true if the dialog has multiple file type choices.
|
||||||
|
virtual bool HasMultipleFileTypeChoicesImpl() = 0;
|
||||||
|
-
|
||||||
|
- std::unique_ptr<SelectFilePolicy> select_file_policy_;
|
||||||
|
};
|
||||||
|
|
||||||
|
SelectFileDialog* CreateSelectFileDialog(
|
||||||
|
diff --git ui/shell_dialogs/select_file_dialog_factory.h ui/shell_dialogs/select_file_dialog_factory.h
|
||||||
|
index 567f50de40b04..1fbac69307bdc 100644
|
||||||
|
--- ui/shell_dialogs/select_file_dialog_factory.h
|
||||||
|
+++ ui/shell_dialogs/select_file_dialog_factory.h
|
||||||
|
@@ -24,6 +24,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogFactory {
|
||||||
|
virtual SelectFileDialog* Create(
|
||||||
|
ui::SelectFileDialog::Listener* listener,
|
||||||
|
std::unique_ptr<ui::SelectFilePolicy> policy) = 0;
|
||||||
|
+
|
||||||
|
+ virtual bool IsCefFactory() const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
diff --git ui/shell_dialogs/select_file_dialog_mac.mm ui/shell_dialogs/select_file_dialog_mac.mm
|
||||||
|
index 605c2278407ce..26ca067d32720 100644
|
||||||
|
--- ui/shell_dialogs/select_file_dialog_mac.mm
|
||||||
|
+++ ui/shell_dialogs/select_file_dialog_mac.mm
|
||||||
|
@@ -100,6 +100,10 @@ void SelectFileDialogImpl::SelectFileImpl(
|
||||||
|
mojo_window->CreateSelectFileDialog(std::move(receiver));
|
||||||
|
} else {
|
||||||
|
NSWindow* ns_window = gfx_window.GetNativeNSWindow();
|
||||||
|
+ if (!ns_window && owning_widget_) {
|
||||||
|
+ NSView* view = ((__bridge NSView*)owning_widget_);
|
||||||
|
+ ns_window = [view window];
|
||||||
|
+ }
|
||||||
|
mojo::MakeSelfOwnedReceiver(
|
||||||
|
std::make_unique<remote_cocoa::SelectFileDialogBridge>(ns_window),
|
||||||
|
std::move(receiver));
|
||||||
|
diff --git ui/shell_dialogs/select_file_dialog_win.cc ui/shell_dialogs/select_file_dialog_win.cc
|
||||||
|
index e2959960598a2..477992b18730b 100644
|
||||||
|
--- ui/shell_dialogs/select_file_dialog_win.cc
|
||||||
|
+++ ui/shell_dialogs/select_file_dialog_win.cc
|
||||||
|
@@ -248,6 +248,8 @@ void SelectFileDialogImpl::SelectFileImpl(
|
||||||
|
HWND owner = owning_window && owning_window->GetRootWindow()
|
||||||
|
? owning_window->GetHost()->GetAcceleratedWidget()
|
||||||
|
: nullptr;
|
||||||
|
+ if (!owner)
|
||||||
|
+ owner = owning_widget_;
|
||||||
|
|
||||||
|
std::unique_ptr<RunState> run_state = BeginRun(owner);
|
||||||
|
|
@ -1,145 +0,0 @@
|
|||||||
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
|
|
||||||
index 936021a313995..2dd2554f8a7c5 100644
|
|
||||||
--- chrome/browser/ui/BUILD.gn
|
|
||||||
+++ chrome/browser/ui/BUILD.gn
|
|
||||||
@@ -10,6 +10,7 @@ import("//build/config/features.gni")
|
|
||||||
import("//build/config/linux/gtk/gtk.gni")
|
|
||||||
import("//build/config/ozone.gni")
|
|
||||||
import("//build/config/ui.gni")
|
|
||||||
+import("//cef/libcef/features/features.gni")
|
|
||||||
import("//chrome/browser/buildflags.gni")
|
|
||||||
import("//chrome/common/features.gni")
|
|
||||||
import("//chromeos/assistant/assistant.gni")
|
|
||||||
@@ -353,6 +354,10 @@ static_library("ui") {
|
|
||||||
"//build/config/compiler:wexit_time_destructors",
|
|
||||||
]
|
|
||||||
|
|
||||||
+ if (enable_cef) {
|
|
||||||
+ configs += [ "//cef/libcef/features:config" ]
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
# Since browser and browser_ui actually depend on each other,
|
|
||||||
# we must omit the dependency from browser_ui to browser.
|
|
||||||
# However, this means browser_ui and browser should more or less
|
|
||||||
@@ -375,6 +380,7 @@ static_library("ui") {
|
|
||||||
"//build:branding_buildflags",
|
|
||||||
"//build:chromeos_buildflags",
|
|
||||||
"//cc/paint",
|
|
||||||
+ "//cef/libcef/features",
|
|
||||||
"//chrome:extra_resources",
|
|
||||||
"//chrome:resources",
|
|
||||||
"//chrome:strings",
|
|
||||||
@@ -5301,6 +5307,7 @@ static_library("ui") {
|
|
||||||
if (enable_basic_printing) {
|
|
||||||
deps += [
|
|
||||||
"//components/printing/browser",
|
|
||||||
+ "//components/printing/common:mojo_interfaces",
|
|
||||||
"//printing",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
diff --git chrome/browser/ui/webui/net_export_ui.cc chrome/browser/ui/webui/net_export_ui.cc
|
|
||||||
index 12edced619355..3a1eb1461ab08 100644
|
|
||||||
--- chrome/browser/ui/webui/net_export_ui.cc
|
|
||||||
+++ chrome/browser/ui/webui/net_export_ui.cc
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
#include "base/task/single_thread_task_runner.h"
|
|
||||||
#include "base/values.h"
|
|
||||||
#include "build/build_config.h"
|
|
||||||
+#include "cef/libcef/features/runtime.h"
|
|
||||||
#include "chrome/browser/browser_process.h"
|
|
||||||
#include "chrome/browser/download/download_prefs.h"
|
|
||||||
#include "chrome/browser/net/net_export_helper.h"
|
|
||||||
@@ -45,6 +46,10 @@
|
|
||||||
#include "net/log/net_log_capture_mode.h"
|
|
||||||
#include "ui/shell_dialogs/select_file_dialog.h"
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+#include "cef/libcef/browser/alloy/alloy_dialog_util.h"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#if BUILDFLAG(IS_ANDROID)
|
|
||||||
#include "components/browser_ui/share/android/intent_helper.h"
|
|
||||||
#endif
|
|
||||||
@@ -142,6 +147,13 @@ class NetExportMessageHandler
|
|
||||||
// NetLog file.
|
|
||||||
void ShowSelectFileDialog(const base::FilePath& default_path);
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ void ShowCefSaveAsDialog(content::WebContents* web_contents);
|
|
||||||
+ void SaveAsDialogDismissed(
|
|
||||||
+ int selected_accept_filter,
|
|
||||||
+ const std::vector<base::FilePath>& file_paths);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
// Cached pointer to SystemNetworkContextManager's NetExportFileWriter.
|
|
||||||
raw_ptr<net_log::NetExportFileWriter> file_writer_;
|
|
||||||
|
|
||||||
@@ -235,6 +247,13 @@ void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) {
|
|
||||||
if (UsingMobileUI()) {
|
|
||||||
StartNetLog(base::FilePath());
|
|
||||||
} else {
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ if (cef::IsAlloyRuntimeEnabled()) {
|
|
||||||
+ ShowCefSaveAsDialog(web_ui()->GetWebContents());
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
base::FilePath initial_dir = last_save_dir.Pointer()->empty() ?
|
|
||||||
DownloadPrefs::FromBrowserContext(
|
|
||||||
web_ui()->GetWebContents()->GetBrowserContext())->DownloadPath() :
|
|
||||||
@@ -251,6 +270,7 @@ void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
|
|
||||||
std::unique_ptr<base::DictionaryValue> ui_thread_polled_data(
|
|
||||||
new base::DictionaryValue());
|
|
||||||
|
|
||||||
+ if (!cef::IsAlloyRuntimeEnabled()) {
|
|
||||||
Profile* profile = Profile::FromWebUI(web_ui());
|
|
||||||
SetIfNotNull(ui_thread_polled_data.get(), "prerenderInfo",
|
|
||||||
chrome_browser_net::GetPrerenderInfo(profile));
|
|
||||||
@@ -260,6 +280,7 @@ void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
|
|
||||||
SetIfNotNull(ui_thread_polled_data.get(), "serviceProviders",
|
|
||||||
chrome_browser_net::GetWindowsServiceProviders());
|
|
||||||
#endif
|
|
||||||
+ }
|
|
||||||
|
|
||||||
file_writer_->StopNetLog(std::move(ui_thread_polled_data));
|
|
||||||
}
|
|
||||||
@@ -375,6 +396,38 @@ void NetExportMessageHandler::ShowSelectFileDialog(
|
|
||||||
&file_type_info, 0, base::FilePath::StringType(), owning_window, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+
|
|
||||||
+void NetExportMessageHandler::ShowCefSaveAsDialog(
|
|
||||||
+ content::WebContents* web_contents) {
|
|
||||||
+ base::FilePath initial_dir;
|
|
||||||
+ if (!last_save_dir.Pointer()->empty())
|
|
||||||
+ initial_dir = *last_save_dir.Pointer();
|
|
||||||
+ base::FilePath initial_path =
|
|
||||||
+ initial_dir.Append(FILE_PATH_LITERAL("chrome-net-export-log.json"));
|
|
||||||
+
|
|
||||||
+ blink::mojom::FileChooserParams params;
|
|
||||||
+ params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
|
||||||
+ params.default_file_name = initial_path;
|
|
||||||
+ params.accept_types.push_back(
|
|
||||||
+ alloy::FilePathTypeToString16(initial_path.Extension()));
|
|
||||||
+
|
|
||||||
+ alloy::RunFileChooser(web_contents, params,
|
|
||||||
+ base::BindOnce(&NetExportMessageHandler::SaveAsDialogDismissed,
|
|
||||||
+ weak_ptr_factory_.GetWeakPtr()));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void NetExportMessageHandler::SaveAsDialogDismissed(
|
|
||||||
+ int selected_accept_filter,
|
|
||||||
+ const std::vector<base::FilePath>& file_paths) {
|
|
||||||
+ if (file_paths.size() == 1) {
|
|
||||||
+ *last_save_dir.Pointer() = file_paths[0].DirName();
|
|
||||||
+ StartNetLog(file_paths[0]);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif // BUILDFLAG(ENABLE_CEF)
|
|
||||||
+
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
NetExportUI::NetExportUI(content::WebUI* web_ui) : WebUIController(web_ui) {
|
|
@ -135,159 +135,6 @@ index f6098966f5b34..da78289b66155 100644
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
|
|
||||||
index 86e16795ce43d..9053975ad42f6 100644
|
|
||||||
--- chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
|
|
||||||
+++ chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
|
|
||||||
@@ -21,6 +21,7 @@
|
|
||||||
#include "base/values.h"
|
|
||||||
#include "build/build_config.h"
|
|
||||||
#include "build/chromeos_buildflags.h"
|
|
||||||
+#include "cef/libcef/features/runtime.h"
|
|
||||||
#include "chrome/browser/app_mode/app_mode_utils.h"
|
|
||||||
#include "chrome/browser/browser_process.h"
|
|
||||||
#include "chrome/browser/download/download_prefs.h"
|
|
||||||
@@ -62,6 +63,10 @@
|
|
||||||
#include "chromeos/lacros/lacros_service.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+#include "cef/libcef/browser/alloy/alloy_dialog_util.h"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
namespace printing {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
@@ -414,16 +419,18 @@ void PdfPrinterHandler::SelectFile(const base::FilePath& default_filename,
|
|
||||||
service->GetRemote<crosapi::mojom::DriveIntegrationService>()
|
|
||||||
->GetMountPointPath(
|
|
||||||
base::BindOnce(&PdfPrinterHandler::OnSaveLocationReady,
|
|
||||||
- weak_ptr_factory_.GetWeakPtr(),
|
|
||||||
+ weak_ptr_factory_.GetWeakPtr(), initiator,
|
|
||||||
std::move(default_filename), prompt_user));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- OnSaveLocationReady(default_filename, prompt_user, GetSaveLocation());
|
|
||||||
+ OnSaveLocationReady(initiator, default_filename, prompt_user,
|
|
||||||
+ GetSaveLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PdfPrinterHandler::OnSaveLocationReady(
|
|
||||||
+ content::WebContents* initiator,
|
|
||||||
const base::FilePath& default_filename,
|
|
||||||
bool prompt_user,
|
|
||||||
const base::FilePath& path) {
|
|
||||||
@@ -441,10 +448,27 @@ void PdfPrinterHandler::OnSaveLocationReady(
|
|
||||||
// If the directory is empty there is no reason to create it or use the
|
|
||||||
// default location.
|
|
||||||
if (path.empty()) {
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ if (cef::IsAlloyRuntimeEnabled()) {
|
|
||||||
+ ShowCefSaveAsDialog(initiator, default_filename, path);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
OnDirectorySelected(default_filename, path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ auto callback = base::BindOnce(&PdfPrinterHandler::OnDirectorySelected,
|
|
||||||
+ weak_ptr_factory_.GetWeakPtr(),
|
|
||||||
+ default_filename);
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ if (cef::IsAlloyRuntimeEnabled()) {
|
|
||||||
+ callback = base::BindOnce(&PdfPrinterHandler::ShowCefSaveAsDialog,
|
|
||||||
+ weak_ptr_factory_.GetWeakPtr(), initiator,
|
|
||||||
+ default_filename);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
// Get default download directory. This will be used as a fallback if the
|
|
||||||
// save directory does not exist.
|
|
||||||
DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(profile_);
|
|
||||||
@@ -452,8 +476,7 @@ void PdfPrinterHandler::OnSaveLocationReady(
|
|
||||||
base::ThreadPool::PostTaskAndReplyWithResult(
|
|
||||||
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
|
|
||||||
base::BindOnce(&SelectSaveDirectory, path, default_path),
|
|
||||||
- base::BindOnce(&PdfPrinterHandler::OnDirectorySelected,
|
|
||||||
- weak_ptr_factory_.GetWeakPtr(), default_filename));
|
|
||||||
+ std::move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PdfPrinterHandler::PostPrintToPdfTask() {
|
|
||||||
@@ -499,6 +522,36 @@ void PdfPrinterHandler::OnDirectorySelected(const base::FilePath& filename,
|
|
||||||
platform_util::GetTopLevel(preview_web_contents_->GetNativeView()), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+
|
|
||||||
+void PdfPrinterHandler::ShowCefSaveAsDialog(content::WebContents* initiator,
|
|
||||||
+ const base::FilePath& filename,
|
|
||||||
+ const base::FilePath& directory) {
|
|
||||||
+ base::FilePath path = directory.Append(filename);
|
|
||||||
+
|
|
||||||
+ blink::mojom::FileChooserParams params;
|
|
||||||
+ params.mode = blink::mojom::FileChooserParams::Mode::kSave;
|
|
||||||
+ params.default_file_name = path;
|
|
||||||
+ params.accept_types.push_back(
|
|
||||||
+ alloy::FilePathTypeToString16(path.Extension()));
|
|
||||||
+
|
|
||||||
+ alloy::RunFileChooser(initiator, params,
|
|
||||||
+ base::BindOnce(&PdfPrinterHandler::SaveAsDialogDismissed,
|
|
||||||
+ weak_ptr_factory_.GetWeakPtr()));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void PdfPrinterHandler::SaveAsDialogDismissed(
|
|
||||||
+ int selected_accept_filter,
|
|
||||||
+ const std::vector<base::FilePath>& file_paths) {
|
|
||||||
+ if (file_paths.size() == 1) {
|
|
||||||
+ FileSelected(file_paths[0], 0, nullptr);
|
|
||||||
+ } else {
|
|
||||||
+ FileSelectionCanceled(nullptr);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif // BUILDFLAG(ENABLE_CEF)
|
|
||||||
+
|
|
||||||
base::FilePath PdfPrinterHandler::GetSaveLocation() const {
|
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
|
||||||
drive::DriveIntegrationService* drive_service =
|
|
||||||
diff --git chrome/browser/ui/webui/print_preview/pdf_printer_handler.h chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
|
|
||||||
index 46c8b1d08b075..1ee95cd7c3240 100644
|
|
||||||
--- chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
|
|
||||||
+++ chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
|
|
||||||
@@ -12,6 +12,7 @@
|
|
||||||
#include "base/memory/ref_counted.h"
|
|
||||||
#include "base/memory/weak_ptr.h"
|
|
||||||
#include "build/chromeos_buildflags.h"
|
|
||||||
+#include "cef/libcef/features/features.h"
|
|
||||||
#include "chrome/browser/ui/webui/print_preview/printer_handler.h"
|
|
||||||
#include "ui/shell_dialogs/select_file_dialog.h"
|
|
||||||
|
|
||||||
@@ -95,10 +96,20 @@ class PdfPrinterHandler : public PrinterHandler,
|
|
||||||
void OnDirectorySelected(const base::FilePath& filename,
|
|
||||||
const base::FilePath& directory);
|
|
||||||
|
|
||||||
- void OnSaveLocationReady(const base::FilePath& default_filename,
|
|
||||||
+ void OnSaveLocationReady(content::WebContents* initiator,
|
|
||||||
+ const base::FilePath& default_filename,
|
|
||||||
bool prompt_user,
|
|
||||||
const base::FilePath& path);
|
|
||||||
|
|
||||||
+#if BUILDFLAG(ENABLE_CEF)
|
|
||||||
+ void ShowCefSaveAsDialog(content::WebContents* initiator,
|
|
||||||
+ const base::FilePath& filename,
|
|
||||||
+ const base::FilePath& directory);
|
|
||||||
+
|
|
||||||
+ void SaveAsDialogDismissed(int selected_accept_filter,
|
|
||||||
+ const std::vector<base::FilePath>& file_paths);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
// Return save location as the Drive mount or fetch from Download Preferences.
|
|
||||||
base::FilePath GetSaveLocation() const;
|
|
||||||
|
|
||||||
diff --git chrome/browser/ui/webui/print_preview/print_preview_ui.cc chrome/browser/ui/webui/print_preview/print_preview_ui.cc
|
diff --git chrome/browser/ui/webui/print_preview/print_preview_ui.cc chrome/browser/ui/webui/print_preview/print_preview_ui.cc
|
||||||
index eba14d78d87ff..7901f000a44b5 100644
|
index eba14d78d87ff..7901f000a44b5 100644
|
||||||
--- chrome/browser/ui/webui/print_preview/print_preview_ui.cc
|
--- chrome/browser/ui/webui/print_preview/print_preview_ui.cc
|
||||||
|
@ -260,12 +260,6 @@ ClientHandler::ClientHandler(Delegate* delegate,
|
|||||||
initial_navigation_(true) {
|
initial_navigation_(true) {
|
||||||
DCHECK(!console_log_file_.empty());
|
DCHECK(!console_log_file_.empty());
|
||||||
|
|
||||||
#if defined(OS_LINUX)
|
|
||||||
// Provide the GTK-based dialog implementation on Linux.
|
|
||||||
dialog_handler_ = new ClientDialogHandlerGtk();
|
|
||||||
print_handler_ = new ClientPrintHandlerGtk();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
resource_manager_ = new CefResourceManager();
|
resource_manager_ = new CefResourceManager();
|
||||||
test_runner::SetupResourceManager(resource_manager_, &string_resource_map_);
|
test_runner::SetupResourceManager(resource_manager_, &string_resource_map_);
|
||||||
|
|
||||||
@ -275,6 +269,34 @@ ClientHandler::ClientHandler(Delegate* delegate,
|
|||||||
mouse_cursor_change_disabled_ =
|
mouse_cursor_change_disabled_ =
|
||||||
command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
|
command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
|
||||||
offline_ = command_line->HasSwitch(switches::kOffline);
|
offline_ = command_line->HasSwitch(switches::kOffline);
|
||||||
|
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
// Optionally use the client-provided dialog implementation.
|
||||||
|
bool use_client_dialogs =
|
||||||
|
command_line->HasSwitch(switches::kUseClientDialogs);
|
||||||
|
|
||||||
|
if (!use_client_dialogs &&
|
||||||
|
command_line->HasSwitch(switches::kMultiThreadedMessageLoop)) {
|
||||||
|
// Default dialogs are not supported in combination with
|
||||||
|
// multi-threaded-message-loop because Chromium doesn't support GDK threads
|
||||||
|
// internally.
|
||||||
|
LOG(WARNING) << "Client dialogs must be used in combination with "
|
||||||
|
"multi-threaded-message-loop.";
|
||||||
|
use_client_dialogs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_client_dialogs && MainContext::Get()->UseViews()) {
|
||||||
|
// Client dialogs cannot be used in combination with Views because the
|
||||||
|
// implementation of ClientDialogHandlerGtk requires a top-level GtkWindow.
|
||||||
|
LOG(ERROR) << "Client dialogs cannot be used in combination with Views.";
|
||||||
|
use_client_dialogs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_client_dialogs) {
|
||||||
|
dialog_handler_ = new ClientDialogHandlerGtk();
|
||||||
|
print_handler_ = new ClientPrintHandlerGtk();
|
||||||
|
}
|
||||||
|
#endif // defined(OS_LINUX)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientHandler::DetachDelegate() {
|
void ClientHandler::DetachDelegate() {
|
||||||
|
@ -136,6 +136,7 @@ GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
|||||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||||
if (root_window) {
|
if (root_window) {
|
||||||
GtkWidget* window = root_window->GetWindowHandle();
|
GtkWidget* window = root_window->GetWindowHandle();
|
||||||
|
DCHECK(window);
|
||||||
if (!window)
|
if (!window)
|
||||||
LOG(ERROR) << "No GtkWindow for browser";
|
LOG(ERROR) << "No GtkWindow for browser";
|
||||||
return GTK_WINDOW(window);
|
return GTK_WINDOW(window);
|
||||||
@ -153,7 +154,6 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
@ -163,7 +163,6 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
|||||||
params.title = title;
|
params.title = title;
|
||||||
params.default_file_path = default_file_path;
|
params.default_file_path = default_file_path;
|
||||||
params.accept_filters = accept_filters;
|
params.accept_filters = accept_filters;
|
||||||
params.selected_accept_filter = selected_accept_filter;
|
|
||||||
params.callback = callback;
|
params.callback = callback;
|
||||||
|
|
||||||
GetWindowAndContinue(
|
GetWindowAndContinue(
|
||||||
@ -221,8 +220,9 @@ void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
|
|||||||
js_dialog_callback_ = nullptr;
|
js_dialog_callback_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
void ClientDialogHandlerGtk::OnFileDialogContinue(
|
||||||
GtkWindow* window) {
|
const OnFileDialogParams& params,
|
||||||
|
GtkWindow* window) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
@ -232,17 +232,14 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
|||||||
GtkFileChooserAction action;
|
GtkFileChooserAction action;
|
||||||
const gchar* accept_button;
|
const gchar* accept_button;
|
||||||
|
|
||||||
// Remove any modifier flags.
|
if (params.mode == FILE_DIALOG_OPEN ||
|
||||||
FileDialogMode mode_type =
|
params.mode == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||||
static_cast<FileDialogMode>(params.mode & FILE_DIALOG_TYPE_MASK);
|
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
|
||||||
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||||
accept_button = "_Open";
|
accept_button = "_Open";
|
||||||
} else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
|
} else if (params.mode == FILE_DIALOG_OPEN_FOLDER) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||||
accept_button = "_Open";
|
accept_button = "_Open";
|
||||||
} else if (mode_type == FILE_DIALOG_SAVE) {
|
} else if (params.mode == FILE_DIALOG_SAVE) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||||
accept_button = "_Save";
|
accept_button = "_Save";
|
||||||
} else {
|
} else {
|
||||||
@ -255,7 +252,7 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
|||||||
if (!params.title.empty()) {
|
if (!params.title.empty()) {
|
||||||
title_str = params.title;
|
title_str = params.title;
|
||||||
} else {
|
} else {
|
||||||
switch (mode_type) {
|
switch (params.mode) {
|
||||||
case FILE_DIALOG_OPEN:
|
case FILE_DIALOG_OPEN:
|
||||||
title_str = "Open File";
|
title_str = "Open File";
|
||||||
break;
|
break;
|
||||||
@ -277,19 +274,10 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
|||||||
title_str.c_str(), GTK_WINDOW(window), action, "_Cancel",
|
title_str.c_str(), GTK_WINDOW(window), action, "_Cancel",
|
||||||
GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, nullptr);
|
GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, nullptr);
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
|
if (params.mode == FILE_DIALOG_OPEN_MULTIPLE)
|
||||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_SAVE) {
|
if (!params.default_file_path.empty() && params.mode == FILE_DIALOG_SAVE) {
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(
|
|
||||||
GTK_FILE_CHOOSER(dialog),
|
|
||||||
!!(params.mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_file_chooser_set_show_hidden(
|
|
||||||
GTK_FILE_CHOOSER(dialog), !(params.mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
|
||||||
|
|
||||||
if (!params.default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
|
|
||||||
const std::string& file_path = params.default_file_path;
|
const std::string& file_path = params.default_file_path;
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
|
|
||||||
@ -310,20 +298,17 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
|||||||
|
|
||||||
std::vector<GtkFileFilter*> filters;
|
std::vector<GtkFileFilter*> filters;
|
||||||
AddFilters(GTK_FILE_CHOOSER(dialog), params.accept_filters, true, &filters);
|
AddFilters(GTK_FILE_CHOOSER(dialog), params.accept_filters, true, &filters);
|
||||||
if (params.selected_accept_filter < static_cast<int>(filters.size())) {
|
|
||||||
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
|
|
||||||
filters[params.selected_accept_filter]);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER ||
|
if (params.mode == FILE_DIALOG_OPEN ||
|
||||||
mode_type == FILE_DIALOG_SAVE) {
|
params.mode == FILE_DIALOG_OPEN_FOLDER ||
|
||||||
|
params.mode == FILE_DIALOG_SAVE) {
|
||||||
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
files.push_back(std::string(filename));
|
files.push_back(std::string(filename));
|
||||||
success = true;
|
success = true;
|
||||||
} else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
} else if (params.mode == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||||
GSList* filenames =
|
GSList* filenames =
|
||||||
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
||||||
if (filenames) {
|
if (filenames) {
|
||||||
@ -339,29 +324,15 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int filter_index = params.selected_accept_filter;
|
|
||||||
if (success) {
|
|
||||||
GtkFileFilter* selected_filter =
|
|
||||||
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
|
|
||||||
if (selected_filter != nullptr) {
|
|
||||||
for (size_t x = 0; x < filters.size(); ++x) {
|
|
||||||
if (filters[x] == selected_filter) {
|
|
||||||
filter_index = x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
params.callback->Continue(filter_index, files);
|
params.callback->Continue(files);
|
||||||
else
|
else
|
||||||
params.callback->Cancel();
|
params.callback->Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params,
|
void ClientDialogHandlerGtk::OnJSDialogContinue(const OnJSDialogParams& params,
|
||||||
GtkWindow* window) {
|
GtkWindow* window) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ class ClientDialogHandlerGtk : public CefDialogHandler,
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_path,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_filters,
|
const std::vector<CefString>& accept_filters,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) override;
|
CefRefPtr<CefFileDialogCallback> callback) override;
|
||||||
|
|
||||||
// CefJSDialogHandler methods.
|
// CefJSDialogHandler methods.
|
||||||
@ -49,10 +48,10 @@ class ClientDialogHandlerGtk : public CefDialogHandler,
|
|||||||
CefString title;
|
CefString title;
|
||||||
CefString default_file_path;
|
CefString default_file_path;
|
||||||
std::vector<CefString> accept_filters;
|
std::vector<CefString> accept_filters;
|
||||||
int selected_accept_filter;
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback;
|
CefRefPtr<CefFileDialogCallback> callback;
|
||||||
};
|
};
|
||||||
void OnFileDialogContinue(OnFileDialogParams params, GtkWindow* window);
|
void OnFileDialogContinue(const OnFileDialogParams& params,
|
||||||
|
GtkWindow* window);
|
||||||
|
|
||||||
struct OnJSDialogParams {
|
struct OnJSDialogParams {
|
||||||
CefRefPtr<CefBrowser> browser;
|
CefRefPtr<CefBrowser> browser;
|
||||||
@ -62,7 +61,7 @@ class ClientDialogHandlerGtk : public CefDialogHandler,
|
|||||||
CefString default_prompt_text;
|
CefString default_prompt_text;
|
||||||
CefRefPtr<CefJSDialogCallback> callback;
|
CefRefPtr<CefJSDialogCallback> callback;
|
||||||
};
|
};
|
||||||
void OnJSDialogContinue(OnJSDialogParams params, GtkWindow* window);
|
void OnJSDialogContinue(const OnJSDialogParams& params, GtkWindow* window);
|
||||||
|
|
||||||
void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
|
void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
|
||||||
base::OnceCallback<void(GtkWindow*)> callback);
|
base::OnceCallback<void(GtkWindow*)> callback);
|
||||||
|
@ -17,7 +17,8 @@ namespace dialog_test {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kTestUrlPath[] = "/dialogs";
|
const char kTestUrlPath[] = "/dialogs";
|
||||||
const char kFileOpenMessageName[] = "DialogTest.FileOpen";
|
const char kFileOpenPngMessageName[] = "DialogTest.FileOpenPng";
|
||||||
|
const char kFileOpenImageMessageName[] = "DialogTest.FileOpenImage";
|
||||||
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
|
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
|
||||||
const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
|
const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
|
||||||
const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
||||||
@ -25,11 +26,9 @@ const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
|||||||
// Store persistent dialog state information.
|
// Store persistent dialog state information.
|
||||||
class DialogState : public base::RefCountedThreadSafe<DialogState> {
|
class DialogState : public base::RefCountedThreadSafe<DialogState> {
|
||||||
public:
|
public:
|
||||||
DialogState()
|
DialogState() : mode_(FILE_DIALOG_OPEN), pending_(false) {}
|
||||||
: mode_(FILE_DIALOG_OPEN), last_selected_filter_(0), pending_(false) {}
|
|
||||||
|
|
||||||
cef_file_dialog_mode_t mode_;
|
cef_file_dialog_mode_t mode_;
|
||||||
int last_selected_filter_;
|
|
||||||
CefString last_file_;
|
CefString last_file_;
|
||||||
bool pending_;
|
bool pending_;
|
||||||
|
|
||||||
@ -45,15 +44,11 @@ class DialogCallback : public CefRunFileDialogCallback {
|
|||||||
: router_callback_(router_callback), dialog_state_(dialog_state) {}
|
: router_callback_(router_callback), dialog_state_(dialog_state) {}
|
||||||
|
|
||||||
virtual void OnFileDialogDismissed(
|
virtual void OnFileDialogDismissed(
|
||||||
int last_selected_filter,
|
|
||||||
const std::vector<CefString>& file_paths) override {
|
const std::vector<CefString>& file_paths) override {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
DCHECK(dialog_state_->pending_);
|
DCHECK(dialog_state_->pending_);
|
||||||
|
|
||||||
if (!file_paths.empty()) {
|
if (!file_paths.empty()) {
|
||||||
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER)
|
|
||||||
dialog_state_->last_selected_filter_ = last_selected_filter;
|
|
||||||
|
|
||||||
dialog_state_->last_file_ = file_paths[0];
|
dialog_state_->last_file_ = file_paths[0];
|
||||||
if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
|
if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
|
||||||
std::string last_file = dialog_state_->last_file_;
|
std::string last_file = dialog_state_->last_file_;
|
||||||
@ -118,25 +113,30 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
|||||||
std::string title;
|
std::string title;
|
||||||
|
|
||||||
const std::string& message_name = request;
|
const std::string& message_name = request;
|
||||||
if (message_name == kFileOpenMessageName) {
|
if (message_name == kFileOpenPngMessageName) {
|
||||||
dialog_state_->mode_ = FILE_DIALOG_OPEN;
|
dialog_state_->mode_ = FILE_DIALOG_OPEN;
|
||||||
title = "My Open Dialog";
|
title = "My Open PNG Dialog";
|
||||||
|
accept_filters.push_back(".png");
|
||||||
|
} else if (message_name == kFileOpenImageMessageName) {
|
||||||
|
dialog_state_->mode_ = FILE_DIALOG_OPEN;
|
||||||
|
title = "My Open Image Dialog";
|
||||||
|
accept_filters.push_back("image/*");
|
||||||
} else if (message_name == kFileOpenMultipleMessageName) {
|
} else if (message_name == kFileOpenMultipleMessageName) {
|
||||||
dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
|
dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
|
||||||
title = "My Open Multiple Dialog";
|
title = "My Open MultiType Dialog";
|
||||||
} else if (message_name == kFileOpenFolderMessageName) {
|
} else if (message_name == kFileOpenFolderMessageName) {
|
||||||
dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
|
dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
|
||||||
title = "My Open Folder Dialog";
|
title = "My Open Folder Dialog";
|
||||||
} else if (message_name == kFileSaveMessageName) {
|
} else if (message_name == kFileSaveMessageName) {
|
||||||
dialog_state_->mode_ = static_cast<cef_file_dialog_mode_t>(
|
dialog_state_->mode_ = FILE_DIALOG_SAVE;
|
||||||
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
|
||||||
title = "My Save Dialog";
|
title = "My Save Dialog";
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
|
if (accept_filters.empty() &&
|
||||||
|
dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
|
||||||
// Build filters based on mime time.
|
// Build filters based on mime time.
|
||||||
accept_filters.push_back("text/*");
|
accept_filters.push_back("text/*");
|
||||||
|
|
||||||
@ -154,7 +154,6 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
|||||||
|
|
||||||
browser->GetHost()->RunFileDialog(
|
browser->GetHost()->RunFileDialog(
|
||||||
dialog_state_->mode_, title, dialog_state_->last_file_, accept_filters,
|
dialog_state_->mode_, title, dialog_state_->last_file_, accept_filters,
|
||||||
dialog_state_->last_selected_filter_,
|
|
||||||
new DialogCallback(callback, dialog_state_));
|
new DialogCallback(callback, dialog_state_));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -312,17 +312,12 @@ void EndTracing(CefRefPtr<CefBrowser> browser) {
|
|||||||
|
|
||||||
// Results in a call to OnFileDialogDismissed.
|
// Results in a call to OnFileDialogDismissed.
|
||||||
browser_->GetHost()->RunFileDialog(
|
browser_->GetHost()->RunFileDialog(
|
||||||
static_cast<cef_file_dialog_mode_t>(FILE_DIALOG_SAVE |
|
FILE_DIALOG_SAVE,
|
||||||
FILE_DIALOG_OVERWRITEPROMPT_FLAG),
|
/*title=*/CefString(), path,
|
||||||
CefString(), // title
|
/*accept_filters=*/std::vector<CefString>(), this);
|
||||||
path,
|
|
||||||
std::vector<CefString>(), // accept_filters
|
|
||||||
0, // selected_accept_filter
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnFileDialogDismissed(
|
void OnFileDialogDismissed(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) override {
|
const std::vector<CefString>& file_paths) override {
|
||||||
if (!file_paths.empty()) {
|
if (!file_paths.empty()) {
|
||||||
// File selected. Results in a call to OnEndTracingComplete.
|
// File selected. Results in a call to OnEndTracingComplete.
|
||||||
@ -370,17 +365,12 @@ void PrintToPDF(CefRefPtr<CefBrowser> browser) {
|
|||||||
accept_filters.push_back(".pdf");
|
accept_filters.push_back(".pdf");
|
||||||
|
|
||||||
// Results in a call to OnFileDialogDismissed.
|
// Results in a call to OnFileDialogDismissed.
|
||||||
browser_->GetHost()->RunFileDialog(
|
browser_->GetHost()->RunFileDialog(FILE_DIALOG_SAVE,
|
||||||
static_cast<cef_file_dialog_mode_t>(FILE_DIALOG_SAVE |
|
/*title=*/CefString(), path,
|
||||||
FILE_DIALOG_OVERWRITEPROMPT_FLAG),
|
accept_filters, this);
|
||||||
CefString(), // title
|
|
||||||
path, accept_filters,
|
|
||||||
0, // selected_accept_filter
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnFileDialogDismissed(
|
void OnFileDialogDismissed(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) override {
|
const std::vector<CefString>& file_paths) override {
|
||||||
if (!file_paths.empty()) {
|
if (!file_paths.empty()) {
|
||||||
CefPdfPrintSettings settings;
|
CefPdfPrintSettings settings;
|
||||||
|
@ -65,10 +65,13 @@ Click a button to show the associated dialog type.
|
|||||||
<br/><input type="button" onclick="show_alert();" value="Show Alert">
|
<br/><input type="button" onclick="show_alert();" value="Show Alert">
|
||||||
<br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
|
<br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
|
||||||
<br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
|
<br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
|
||||||
<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
|
<br/>input type="file" (.png): <input type="file" name="pic" accept=".png">
|
||||||
|
<br/>input type="file" (image/*): <input type="file" name="pic" accept="image/*">
|
||||||
|
<br/>input type="file" (multiple types): <input type="file" name="pic" accept="text/*,.js,.css,image/*">
|
||||||
<br/>input type="file" (directory): <input type="file" webkitdirectory accept="text/*,.js,.css,image/*">
|
<br/>input type="file" (directory): <input type="file" webkitdirectory accept="text/*,.js,.css,image/*">
|
||||||
<br/><input type="button" onclick="show_file_dialog('fo', 'FileOpen');" value="Show File Open" disabled="true"> <span id="fo"></span>
|
<br/><input type="button" onclick="show_file_dialog('fop', 'FileOpenPng');" value="Show File Open (.png)" disabled="true"> <span id="fop"></span>
|
||||||
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open Multiple" disabled="true"> <span id="fom"></span>
|
<br/><input type="button" onclick="show_file_dialog('foi', 'FileOpenImage');" value="Show File Open (image/*)" disabled="true"> <span id="foi"></span>
|
||||||
|
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open (multiple types/files)" disabled="true"> <span id="fom"></span>
|
||||||
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder" disabled="true"> <span id="fof"></span>
|
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder" disabled="true"> <span id="fof"></span>
|
||||||
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save" disabled="true"> <span id="fs"></span>
|
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save" disabled="true"> <span id="fs"></span>
|
||||||
<p id="time"></p>
|
<p id="time"></p>
|
||||||
|
@ -19,7 +19,6 @@ class DialogTestHandler : public TestHandler {
|
|||||||
: mode(dialog_mode),
|
: mode(dialog_mode),
|
||||||
title("Test Title"),
|
title("Test Title"),
|
||||||
default_file_name("Test File Name"),
|
default_file_name("Test File Name"),
|
||||||
selected_accept_filter(1), // Something other than 0 for testing.
|
|
||||||
callback_async(false),
|
callback_async(false),
|
||||||
callback_cancel(false) {
|
callback_cancel(false) {
|
||||||
accept_types.push_back("text/*");
|
accept_types.push_back("text/*");
|
||||||
@ -31,7 +30,6 @@ class DialogTestHandler : public TestHandler {
|
|||||||
CefString title;
|
CefString title;
|
||||||
CefString default_file_name;
|
CefString default_file_name;
|
||||||
std::vector<CefString> accept_types;
|
std::vector<CefString> accept_types;
|
||||||
int selected_accept_filter;
|
|
||||||
|
|
||||||
bool callback_async; // True if the callback should execute asynchronously.
|
bool callback_async; // True if the callback should execute asynchronously.
|
||||||
bool callback_cancel; // True if the callback should cancel.
|
bool callback_cancel; // True if the callback should cancel.
|
||||||
@ -43,16 +41,12 @@ class DialogTestHandler : public TestHandler {
|
|||||||
explicit Callback(DialogTestHandler* handler) : handler_(handler) {}
|
explicit Callback(DialogTestHandler* handler) : handler_(handler) {}
|
||||||
|
|
||||||
void OnFileDialogDismissed(
|
void OnFileDialogDismissed(
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<CefString>& file_paths) override {
|
const std::vector<CefString>& file_paths) override {
|
||||||
handler_->got_onfiledialogdismissed_.yes();
|
handler_->got_onfiledialogdismissed_.yes();
|
||||||
|
|
||||||
if (handler_->config_.callback_cancel) {
|
if (handler_->config_.callback_cancel) {
|
||||||
EXPECT_EQ(0, selected_accept_filter);
|
|
||||||
EXPECT_TRUE(file_paths.empty());
|
EXPECT_TRUE(file_paths.empty());
|
||||||
} else {
|
} else {
|
||||||
EXPECT_EQ(handler_->config_.selected_accept_filter,
|
|
||||||
selected_accept_filter);
|
|
||||||
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
|
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,18 +75,16 @@ class DialogTestHandler : public TestHandler {
|
|||||||
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefFrame> frame,
|
CefRefPtr<CefFrame> frame,
|
||||||
int httpStatusCode) override {
|
int httpStatusCode) override {
|
||||||
browser->GetHost()->RunFileDialog(
|
browser->GetHost()->RunFileDialog(config_.mode, config_.title,
|
||||||
config_.mode, config_.title, config_.default_file_name,
|
config_.default_file_name,
|
||||||
config_.accept_types, config_.selected_accept_filter,
|
config_.accept_types, new Callback(this));
|
||||||
new Callback(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteCallback(CefRefPtr<CefFileDialogCallback> callback) {
|
void ExecuteCallback(CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
if (config_.callback_cancel)
|
if (config_.callback_cancel)
|
||||||
callback->Cancel();
|
callback->Cancel();
|
||||||
else
|
else
|
||||||
callback->Continue(config_.selected_accept_filter,
|
callback->Continue(config_.callback_paths);
|
||||||
config_.callback_paths);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CefDialogHandler
|
// CefDialogHandler
|
||||||
@ -101,7 +93,6 @@ class DialogTestHandler : public TestHandler {
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_name,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_types,
|
||||||
int selected_accept_filter,
|
|
||||||
CefRefPtr<CefFileDialogCallback> callback) override {
|
CefRefPtr<CefFileDialogCallback> callback) override {
|
||||||
got_onfiledialog_.yes();
|
got_onfiledialog_.yes();
|
||||||
|
|
||||||
@ -155,21 +146,6 @@ TEST(DialogTest, FileEmptyParams) {
|
|||||||
ReleaseAndWaitForDestructor(handler);
|
ReleaseAndWaitForDestructor(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DialogTest, FileAdditionalFlags) {
|
|
||||||
DialogTestHandler::TestConfig config(static_cast<cef_file_dialog_mode_t>(
|
|
||||||
FILE_DIALOG_OPEN | FILE_DIALOG_HIDEREADONLY_FLAG |
|
|
||||||
FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
|
||||||
config.title.clear();
|
|
||||||
config.default_file_name.clear();
|
|
||||||
config.accept_types.clear();
|
|
||||||
config.callback_async = false;
|
|
||||||
config.callback_cancel = false;
|
|
||||||
|
|
||||||
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
|
|
||||||
handler->ExecuteTest();
|
|
||||||
ReleaseAndWaitForDestructor(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(DialogTest, FileOpen) {
|
TEST(DialogTest, FileOpen) {
|
||||||
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
|
||||||
config.callback_async = false;
|
config.callback_async = false;
|
||||||
|
@ -50,6 +50,7 @@ const char kShowChromeToolbar[] = "show-chrome-toolbar";
|
|||||||
const char kInitialShowState[] = "initial-show-state";
|
const char kInitialShowState[] = "initial-show-state";
|
||||||
const char kHideChromeStatusBubble[] = "hide-chrome-status-bubble";
|
const char kHideChromeStatusBubble[] = "hide-chrome-status-bubble";
|
||||||
const char kUseDefaultPopup[] = "use-default-popup";
|
const char kUseDefaultPopup[] = "use-default-popup";
|
||||||
|
const char kUseClientDialogs[] = "use-client-dialogs";
|
||||||
|
|
||||||
} // namespace switches
|
} // namespace switches
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
@ -44,6 +44,7 @@ extern const char kShowChromeToolbar[];
|
|||||||
extern const char kInitialShowState[];
|
extern const char kInitialShowState[];
|
||||||
extern const char kHideChromeStatusBubble[];
|
extern const char kHideChromeStatusBubble[];
|
||||||
extern const char kUseDefaultPopup[];
|
extern const char kUseDefaultPopup[];
|
||||||
|
extern const char kUseClientDialogs[];
|
||||||
|
|
||||||
} // namespace switches
|
} // namespace switches
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
Loading…
x
Reference in New Issue
Block a user