fix: revert required portal version for file chooser dialogs (#45193)
This commit is contained in:
parent
9dccc9f4b4
commit
2e35a065ba
4 changed files with 158 additions and 16 deletions
|
@ -241,6 +241,13 @@ Force using discrete GPU when there are multiple GPUs available.
|
||||||
|
|
||||||
Force using integrated GPU when there are multiple GPUs available.
|
Force using integrated GPU when there are multiple GPUs available.
|
||||||
|
|
||||||
|
### --xdg-portal-required-version=`version`
|
||||||
|
|
||||||
|
Sets the minimum required version of XDG portal implementation to `version`
|
||||||
|
in order to use the portal backend for file dialogs on linux. File dialogs
|
||||||
|
will fallback to using gtk or kde depending on the desktop environment when
|
||||||
|
the required version is unavailable. Current default is set to `3`.
|
||||||
|
|
||||||
## Node.js Flags
|
## Node.js Flags
|
||||||
|
|
||||||
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
|
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
|
||||||
|
|
|
@ -78,6 +78,11 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note:** On Linux `defaultPath` is not supported when using portal file chooser
|
||||||
|
dialogs unless the portal backend is version 4 or higher. You can use `--xdg-portal-required-version`
|
||||||
|
[command-line switch](./command-line-switches.md#--xdg-portal-required-versionversion)
|
||||||
|
to force gtk or kde dialogs.
|
||||||
|
|
||||||
### `dialog.showOpenDialog([window, ]options)`
|
### `dialog.showOpenDialog([window, ]options)`
|
||||||
|
|
||||||
* `window` [BaseWindow](base-window.md) (optional)
|
* `window` [BaseWindow](base-window.md) (optional)
|
||||||
|
@ -150,6 +155,11 @@ dialog.showOpenDialog(mainWindow, {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note:** On Linux `defaultPath` is not supported when using portal file chooser
|
||||||
|
dialogs unless the portal backend is version 4 or higher. You can use `--xdg-portal-required-version`
|
||||||
|
[command-line switch](./command-line-switches.md#--xdg-portal-required-versionversion)
|
||||||
|
to force gtk or kde dialogs.
|
||||||
|
|
||||||
### `dialog.showSaveDialogSync([window, ]options)`
|
### `dialog.showSaveDialogSync([window, ]options)`
|
||||||
|
|
||||||
* `window` [BaseWindow](base-window.md) (optional)
|
* `window` [BaseWindow](base-window.md) (optional)
|
||||||
|
|
|
@ -199,19 +199,67 @@ index 58985ce62dc569256bad5e94de9c0d125fc470d0..33436784b691c860d58f8b4dfcc6718e
|
||||||
&SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this,
|
&SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this,
|
||||||
parent));
|
parent));
|
||||||
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.cc b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.cc b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||||
index d94540d0a7bf90f57acdaf8ca6665cf283a646bf..7a99193c3ed192fc80f929dfabdc95d2c308a87e 100644
|
index d94540d0a7bf90f57acdaf8ca6665cf283a646bf..e8578b4853d6b82102b29046bdd07c8b80039846 100644
|
||||||
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||||
+++ b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
+++ b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||||
@@ -39,7 +39,7 @@ constexpr char kMethodStartServiceByName[] = "StartServiceByName";
|
@@ -7,6 +7,7 @@
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "base/containers/contains.h"
|
||||||
|
+#include "base/command_line.h"
|
||||||
|
#include "base/functional/bind.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/no_destructor.h"
|
||||||
|
@@ -39,6 +40,8 @@ constexpr char kMethodStartServiceByName[] = "StartServiceByName";
|
||||||
constexpr char kXdgPortalService[] = "org.freedesktop.portal.Desktop";
|
constexpr char kXdgPortalService[] = "org.freedesktop.portal.Desktop";
|
||||||
constexpr char kXdgPortalObject[] = "/org/freedesktop/portal/desktop";
|
constexpr char kXdgPortalObject[] = "/org/freedesktop/portal/desktop";
|
||||||
|
|
||||||
-constexpr int kXdgPortalRequiredVersion = 3;
|
+// Version 4 includes support for current_folder option to the OpenFile method via
|
||||||
+constexpr int kXdgPortalRequiredVersion = 4;
|
+// https://github.com/flatpak/xdg-desktop-portal/commit/71165a5.
|
||||||
|
constexpr int kXdgPortalRequiredVersion = 3;
|
||||||
|
|
||||||
constexpr char kXdgPortalRequestInterfaceName[] =
|
constexpr char kXdgPortalRequestInterfaceName[] =
|
||||||
"org.freedesktop.portal.Request";
|
@@ -67,6 +70,7 @@ constexpr char kFileUriPrefix[] = "file://";
|
||||||
@@ -216,6 +216,8 @@ void SelectFileDialogLinuxPortal::SelectFileImpl(
|
|
||||||
|
// Time to wait for the notification service to start, in milliseconds.
|
||||||
|
constexpr base::TimeDelta kStartServiceTimeout = base::Seconds(1);
|
||||||
|
+const char kXdgPortalRequiredVersionFlag[] = "xdg-portal-required-version";
|
||||||
|
|
||||||
|
struct FileChooserProperties : dbus::PropertySet {
|
||||||
|
dbus::Property<uint32_t> version;
|
||||||
|
@@ -173,10 +177,18 @@ void SelectFileDialogLinuxPortal::StartAvailabilityTestInBackground() {
|
||||||
|
if (GetAvailabilityTestCompletionFlag()->IsSet())
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ auto* cmd = base::CommandLine::ForCurrentProcess();
|
||||||
|
+ unsigned int xdg_portal_required_version;
|
||||||
|
+ if (!base::StringToUint(cmd->GetSwitchValueASCII(kXdgPortalRequiredVersionFlag),
|
||||||
|
+ &xdg_portal_required_version)) {
|
||||||
|
+ xdg_portal_required_version = kXdgPortalRequiredVersion;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
dbus_thread_linux::GetTaskRunner()->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(
|
||||||
|
- &SelectFileDialogLinuxPortal::CheckPortalAvailabilityOnBusThread));
|
||||||
|
+ &SelectFileDialogLinuxPortal::CheckPortalAvailabilityOnBusThread,
|
||||||
|
+ xdg_portal_required_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
@@ -187,6 +199,11 @@ bool SelectFileDialogLinuxPortal::IsPortalAvailable() {
|
||||||
|
return is_portal_available_;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// static
|
||||||
|
+int SelectFileDialogLinuxPortal::GetPortalVersion() {
|
||||||
|
+ return available_portal_version_;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// static
|
||||||
|
void SelectFileDialogLinuxPortal::DestroyPortalConnection() {
|
||||||
|
dbus_thread_linux::GetTaskRunner()->PostTask(
|
||||||
|
@@ -216,6 +233,8 @@ void SelectFileDialogLinuxPortal::SelectFileImpl(
|
||||||
weak_factory_.GetWeakPtr()));
|
weak_factory_.GetWeakPtr()));
|
||||||
info_->type = type;
|
info_->type = type;
|
||||||
info_->main_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
|
info_->main_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
|
||||||
|
@ -220,7 +268,37 @@ index d94540d0a7bf90f57acdaf8ca6665cf283a646bf..7a99193c3ed192fc80f929dfabdc95d2
|
||||||
|
|
||||||
if (owning_window) {
|
if (owning_window) {
|
||||||
if (auto* root = owning_window->GetRootWindow()) {
|
if (auto* root = owning_window->GetRootWindow()) {
|
||||||
@@ -552,7 +554,9 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
@@ -262,7 +281,8 @@ bool SelectFileDialogLinuxPortal::HasMultipleFileTypeChoicesImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
-void SelectFileDialogLinuxPortal::CheckPortalAvailabilityOnBusThread() {
|
||||||
|
+void SelectFileDialogLinuxPortal::CheckPortalAvailabilityOnBusThread(
|
||||||
|
+ unsigned int xdg_portal_required_version) {
|
||||||
|
DCHECK(dbus_thread_linux::GetTaskRunner()->RunsTasksInCurrentSequence());
|
||||||
|
base::AtomicFlag* availability_test_complete =
|
||||||
|
GetAvailabilityTestCompletionFlag();
|
||||||
|
@@ -283,11 +303,18 @@ void SelectFileDialogLinuxPortal::CheckPortalAvailabilityOnBusThread() {
|
||||||
|
FileChooserProperties properties(portal);
|
||||||
|
if (!properties.GetAndBlock(&properties.version)) {
|
||||||
|
LOG(ERROR) << "Failed to read portal version property";
|
||||||
|
- } else if (properties.version.value() >= kXdgPortalRequiredVersion) {
|
||||||
|
+ } else if (properties.version.value() >= xdg_portal_required_version) {
|
||||||
|
is_portal_available_ = true;
|
||||||
|
+ available_portal_version_ = properties.version.value();
|
||||||
|
+ } else {
|
||||||
|
+ VLOG(1) << "File chooser portal available version: "
|
||||||
|
+ << properties.version.value();
|
||||||
|
+ available_portal_version_ = properties.version.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ VLOG(1) << "File chooser portal expected version: "
|
||||||
|
+ << xdg_portal_required_version;
|
||||||
|
VLOG(1) << "File chooser portal available: "
|
||||||
|
<< (is_portal_available_ ? "yes" : "no");
|
||||||
|
availability_test_complete->Set();
|
||||||
|
@@ -552,7 +579,9 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||||
response_handle_token);
|
response_handle_token);
|
||||||
|
|
||||||
if (type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER) {
|
if (type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER) {
|
||||||
|
@ -231,7 +309,7 @@ index d94540d0a7bf90f57acdaf8ca6665cf283a646bf..7a99193c3ed192fc80f929dfabdc95d2
|
||||||
l10n_util::GetStringUTF8(
|
l10n_util::GetStringUTF8(
|
||||||
IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON));
|
IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON));
|
||||||
}
|
}
|
||||||
@@ -561,12 +565,13 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
@@ -561,6 +590,8 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||||
type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER ||
|
type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER ||
|
||||||
type == SelectFileDialog::Type::SELECT_EXISTING_FOLDER) {
|
type == SelectFileDialog::Type::SELECT_EXISTING_FOLDER) {
|
||||||
AppendBoolOption(&options_writer, kFileChooserOptionDirectory, true);
|
AppendBoolOption(&options_writer, kFileChooserOptionDirectory, true);
|
||||||
|
@ -240,18 +318,29 @@ index d94540d0a7bf90f57acdaf8ca6665cf283a646bf..7a99193c3ed192fc80f929dfabdc95d2
|
||||||
} else if (type == SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE) {
|
} else if (type == SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE) {
|
||||||
AppendBoolOption(&options_writer, kFileChooserOptionMultiple, true);
|
AppendBoolOption(&options_writer, kFileChooserOptionMultiple, true);
|
||||||
}
|
}
|
||||||
|
@@ -874,6 +905,7 @@ SelectFileDialogLinuxPortal::DialogInfo::ConvertUrisToPaths(
|
||||||
|
}
|
||||||
|
|
||||||
- if (type == SelectFileDialog::Type::SELECT_SAVEAS_FILE &&
|
bool SelectFileDialogLinuxPortal::is_portal_available_ = false;
|
||||||
- !default_path.empty()) {
|
+unsigned int SelectFileDialogLinuxPortal::available_portal_version_ = 0;
|
||||||
+ if (!default_path.empty()) {
|
int SelectFileDialogLinuxPortal::handle_token_counter_ = 0;
|
||||||
if (default_path_exists) {
|
|
||||||
// If this is an existing directory, navigate to that directory, with no
|
} // namespace ui
|
||||||
// filename.
|
|
||||||
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.h b/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.h b/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
||||||
index 47e3b0e658858ba5f3219f04d258bdf6dd7c26ed..ff8eaabb406cdf759f7a62725171aaf9f74ce183 100644
|
index 47e3b0e658858ba5f3219f04d258bdf6dd7c26ed..7124f65d801b086cf39f3640027b3deeca9b6dca 100644
|
||||||
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
||||||
+++ b/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
+++ b/ui/shell_dialogs/select_file_dialog_linux_portal.h
|
||||||
@@ -117,6 +117,8 @@ class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
|
@@ -44,6 +44,9 @@ class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
|
||||||
|
// test from above has not yet completed (which should generally not happen).
|
||||||
|
static bool IsPortalAvailable();
|
||||||
|
|
||||||
|
+ // Get version of portal if available.
|
||||||
|
+ static int GetPortalVersion();
|
||||||
|
+
|
||||||
|
// Destroys the connection to the bus.
|
||||||
|
static void DestroyPortalConnection();
|
||||||
|
|
||||||
|
@@ -117,6 +120,8 @@ class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
|
||||||
Type type;
|
Type type;
|
||||||
// The task runner the SelectFileImpl method was called on.
|
// The task runner the SelectFileImpl method was called on.
|
||||||
scoped_refptr<base::SequencedTaskRunner> main_task_runner;
|
scoped_refptr<base::SequencedTaskRunner> main_task_runner;
|
||||||
|
@ -260,3 +349,23 @@ index 47e3b0e658858ba5f3219f04d258bdf6dd7c26ed..ff8eaabb406cdf759f7a62725171aaf9
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class base::RefCountedThreadSafe<DialogInfo>;
|
friend class base::RefCountedThreadSafe<DialogInfo>;
|
||||||
|
@@ -173,7 +178,8 @@ class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
|
||||||
|
};
|
||||||
|
|
||||||
|
// D-Bus configuration and initialization.
|
||||||
|
- static void CheckPortalAvailabilityOnBusThread();
|
||||||
|
+ static void CheckPortalAvailabilityOnBusThread(
|
||||||
|
+ unsigned int xdg_portal_required_version);
|
||||||
|
static bool IsPortalRunningOnBusThread(dbus::ObjectProxy* dbus_proxy);
|
||||||
|
static bool IsPortalActivatableOnBusThread(dbus::ObjectProxy* dbus_proxy);
|
||||||
|
|
||||||
|
@@ -207,6 +213,9 @@ class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
|
||||||
|
// Written by the D-Bus thread and read by the UI thread.
|
||||||
|
static bool is_portal_available_;
|
||||||
|
|
||||||
|
+ // Written by the D-Bus thread and read by the UI thread.
|
||||||
|
+ static unsigned int available_portal_version_;
|
||||||
|
+
|
||||||
|
// Used by the D-Bus thread to generate unique handle tokens.
|
||||||
|
static int handle_token_counter_;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "shell/common/gin_converters/file_path_converter.h"
|
#include "shell/common/gin_converters/file_path_converter.h"
|
||||||
#include "ui/gtk/select_file_dialog_linux_gtk.h" // nogncheck
|
#include "ui/gtk/select_file_dialog_linux_gtk.h" // nogncheck
|
||||||
#include "ui/shell_dialogs/select_file_dialog.h"
|
#include "ui/shell_dialogs/select_file_dialog.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_dialog_linux_portal.h"
|
||||||
|
#include "ui/shell_dialogs/select_file_policy.h"
|
||||||
#include "ui/shell_dialogs/selected_file_info.h"
|
#include "ui/shell_dialogs/selected_file_info.h"
|
||||||
|
|
||||||
namespace file_dialog {
|
namespace file_dialog {
|
||||||
|
@ -59,6 +61,18 @@ ui::SelectFileDialog::FileTypeInfo GetFilterInfo(const Filters& filters) {
|
||||||
return file_type_info;
|
return file_type_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LogIfNeededAboutUnsupportedPortalFeature(const DialogSettings& settings) {
|
||||||
|
if (!settings.default_path.empty() &&
|
||||||
|
ui::SelectFileDialogLinuxPortal::IsPortalAvailable() &&
|
||||||
|
ui::SelectFileDialogLinuxPortal::GetPortalVersion() < 4) {
|
||||||
|
LOG(INFO) << "Available portal version "
|
||||||
|
<< ui::SelectFileDialogLinuxPortal::GetPortalVersion()
|
||||||
|
<< " does not support defaultPath option, try the non-portal"
|
||||||
|
<< " file chooser dialogs by launching with"
|
||||||
|
<< " --xdg-portal-required-version";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FileChooserDialog : public ui::SelectFileDialog::Listener {
|
class FileChooserDialog : public ui::SelectFileDialog::Listener {
|
||||||
public:
|
public:
|
||||||
enum class DialogType { OPEN, SAVE };
|
enum class DialogType { OPEN, SAVE };
|
||||||
|
@ -201,6 +215,7 @@ class FileChooserDialog : public ui::SelectFileDialog::Listener {
|
||||||
|
|
||||||
bool ShowOpenDialogSync(const DialogSettings& settings,
|
bool ShowOpenDialogSync(const DialogSettings& settings,
|
||||||
std::vector<base::FilePath>* paths) {
|
std::vector<base::FilePath>* paths) {
|
||||||
|
LogIfNeededAboutUnsupportedPortalFeature(settings);
|
||||||
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
|
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
|
||||||
auto cb = base::BindOnce(
|
auto cb = base::BindOnce(
|
||||||
[](base::RepeatingClosure cb, std::vector<base::FilePath>* file_paths,
|
[](base::RepeatingClosure cb, std::vector<base::FilePath>* file_paths,
|
||||||
|
@ -218,6 +233,7 @@ bool ShowOpenDialogSync(const DialogSettings& settings,
|
||||||
|
|
||||||
void ShowOpenDialog(const DialogSettings& settings,
|
void ShowOpenDialog(const DialogSettings& settings,
|
||||||
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
gin_helper::Promise<gin_helper::Dictionary> promise) {
|
||||||
|
LogIfNeededAboutUnsupportedPortalFeature(settings);
|
||||||
FileChooserDialog* dialog = new FileChooserDialog();
|
FileChooserDialog* dialog = new FileChooserDialog();
|
||||||
dialog->RunOpenDialog(std::move(promise), settings);
|
dialog->RunOpenDialog(std::move(promise), settings);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue