1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_LINUX_PORTAL_H_
#define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_LINUX_PORTAL_H_
#include <memory>
#include <optional>
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "components/dbus/properties/types.h"
#include "components/dbus/xdg/request.h"
#include "dbus/bus.h"
#include "ui/shell_dialogs/select_file_dialog_linux.h"
namespace ui {
using OnSelectFileExecutedCallback =
base::OnceCallback<void(std::vector<base::FilePath> paths,
std::string current_filter)>;
using OnSelectFileCanceledCallback = base::OnceCallback<void()>;
// Implementation of SelectFileDialog that has the XDG file chooser portal show
// a platform-dependent file selection dialog. This acts as a modal dialog.
class SelectFileDialogLinuxPortal : public SelectFileDialogLinux {
public:
SelectFileDialogLinuxPortal(Listener* listener,
std::unique_ptr<ui::SelectFilePolicy> policy);
SelectFileDialogLinuxPortal(const SelectFileDialogLinuxPortal& other) =
delete;
SelectFileDialogLinuxPortal& operator=(
const SelectFileDialogLinuxPortal& other) = delete;
// Starts running a test to check for the presence of the file chooser portal.
// Must be called on the UI thread. This should only be called once,
// preferably around program start.
static void StartAvailabilityTestInBackground();
// Checks if the file chooser portal is available. Logs a warning if the
// availability test has not yet completed.
static bool IsPortalAvailable();
protected:
~SelectFileDialogLinuxPortal() override;
// BaseShellDialog:
bool IsRunning(gfx::NativeWindow parent_window) const override;
// SelectFileDialog:
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,
const GURL* caller) override;
bool HasMultipleFileTypeChoicesImpl() override;
private:
// Glob-style patterns are indicated by 0, MIME types by 1. Patterns are
// case-sensitive.
using DbusFilterPattern = DbusStruct<DbusUint32, DbusString>;
using DbusFilterPatterns = DbusArray<DbusFilterPattern>;
// The first string is a user-visible name for the filter.
using DbusFilter = DbusStruct<DbusString, DbusFilterPatterns>;
using DbusFilters = DbusArray<DbusFilter>;
// A named set of patterns used as a dialog filter.
struct PortalFilter {
PortalFilter();
PortalFilter(const PortalFilter& other);
PortalFilter(PortalFilter&& other);
~PortalFilter();
PortalFilter& operator=(const PortalFilter& other) = default;
PortalFilter& operator=(PortalFilter&& other) = default;
std::string name;
std::vector<std::string> patterns;
};
// A set of PortalFilters, potentially with a default.
struct PortalFilterSet {
PortalFilterSet();
PortalFilterSet(const PortalFilterSet& other);
PortalFilterSet(PortalFilterSet&& other);
~PortalFilterSet();
PortalFilterSet& operator=(const PortalFilterSet& other) = default;
PortalFilterSet& operator=(PortalFilterSet&& other) = default;
std::vector<PortalFilter> filters;
std::optional<PortalFilter> default_filter;
};
PortalFilterSet BuildFilterSet();
void SelectFileImplWithParentHandle(
std::u16string title,
base::FilePath default_path,
PortalFilterSet filter_set,
base::FilePath::StringType default_extension,
std::string parent_handle);
void SelectFileImplOnMainThread(std::u16string title,
base::FilePath default_path,
const bool default_path_exists,
PortalFilterSet filter_set,
base::FilePath::StringType default_extension,
std::string parent_handle);
DbusDictionary BuildOptionsDictionary(const base::FilePath& default_path,
bool default_path_exists,
const PortalFilterSet& filter_set);
DbusFilter MakeFilterStruct(const PortalFilter& filter);
void MakeFileChooserRequest(const std::string& method,
const std::string& title,
DbusDictionary options,
std::string parent_handle);
void OnFileChooserResponse(
base::expected<DbusDictionary, dbus_xdg::ResponseError> results);
void CompleteOpen(std::vector<base::FilePath> paths,
std::string current_filter);
void CancelOpen();
void DialogCreatedOnInvoker();
void CompleteOpenOnInvoker(std::vector<base::FilePath> paths,
std::string current_filter);
void CancelOpenOnInvoker();
// Removes the DialogInfo parent.
void UnparentOnInvoker();
Type type_ = SELECT_NONE;
// The task runner the SelectFileImpl method was called on.
scoped_refptr<base::SequencedTaskRunner> invoker_task_runner_;
// This should be used by the invoker task runner.
base::WeakPtr<aura::WindowTreeHost> host_;
std::vector<PortalFilter> filters_;
// The Request representing an in-flight file chooser call, if any.
// We keep this alive until the response arrives or until the dialog
// is destroyed, whichever comes first.
std::unique_ptr<dbus_xdg::Request> file_chooser_request_;
// Event handling on the parent window is disabled while the dialog is active
// to make the dialog modal. This closure should be run when the dialog is
// closed to reenable event handling.
base::OnceClosure reenable_window_event_handling_;
};
} // namespace ui
#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_LINUX_PORTAL_H_
|