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:
Marshall Greenblatt
2022-04-15 15:55:23 -04:00
parent edef01f579
commit 2ea7459a89
75 changed files with 1566 additions and 2231 deletions

View File

@@ -19,7 +19,6 @@ class DialogTestHandler : public TestHandler {
: mode(dialog_mode),
title("Test Title"),
default_file_name("Test File Name"),
selected_accept_filter(1), // Something other than 0 for testing.
callback_async(false),
callback_cancel(false) {
accept_types.push_back("text/*");
@@ -31,7 +30,6 @@ class DialogTestHandler : public TestHandler {
CefString title;
CefString default_file_name;
std::vector<CefString> accept_types;
int selected_accept_filter;
bool callback_async; // True if the callback should execute asynchronously.
bool callback_cancel; // True if the callback should cancel.
@@ -43,16 +41,12 @@ class DialogTestHandler : public TestHandler {
explicit Callback(DialogTestHandler* handler) : handler_(handler) {}
void OnFileDialogDismissed(
int selected_accept_filter,
const std::vector<CefString>& file_paths) override {
handler_->got_onfiledialogdismissed_.yes();
if (handler_->config_.callback_cancel) {
EXPECT_EQ(0, selected_accept_filter);
EXPECT_TRUE(file_paths.empty());
} else {
EXPECT_EQ(handler_->config_.selected_accept_filter,
selected_accept_filter);
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
}
@@ -81,18 +75,16 @@ class DialogTestHandler : public TestHandler {
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
browser->GetHost()->RunFileDialog(
config_.mode, config_.title, config_.default_file_name,
config_.accept_types, config_.selected_accept_filter,
new Callback(this));
browser->GetHost()->RunFileDialog(config_.mode, config_.title,
config_.default_file_name,
config_.accept_types, new Callback(this));
}
void ExecuteCallback(CefRefPtr<CefFileDialogCallback> callback) {
if (config_.callback_cancel)
callback->Cancel();
else
callback->Continue(config_.selected_accept_filter,
config_.callback_paths);
callback->Continue(config_.callback_paths);
}
// CefDialogHandler
@@ -101,7 +93,6 @@ class DialogTestHandler : public TestHandler {
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
int selected_accept_filter,
CefRefPtr<CefFileDialogCallback> callback) override {
got_onfiledialog_.yes();
@@ -155,21 +146,6 @@ TEST(DialogTest, FileEmptyParams) {
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) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.callback_async = false;