summaryrefslogtreecommitdiff
path: root/Userland/Services/FileSystemAccessServer
diff options
context:
space:
mode:
authorTimothy <timmot@users.noreply.github.com>2021-07-12 01:16:26 +1000
committerAndreas Kling <kling@serenityos.org>2021-07-18 17:21:28 +0200
commit38594dde7901e8e3cd5d114251df08d12549ee54 (patch)
tree6427050fc770f8bbf08503949d0655427af1258d /Userland/Services/FileSystemAccessServer
parentab353fd4e16d2ddae8098b4bc2d71682497eb375 (diff)
downloadserenity-38594dde7901e8e3cd5d114251df08d12549ee54.zip
FileSystemAccessServer+TextEditor: Implement cross-process modal prompts
This transitions from synchronous IPC calls to asynchronous IPC calls provided through a synchronous interface in LibFileSystemAccessClient which allows the parent Application to stay responsive. It achieves this with Promise which is pumping the Application event loop while waiting for the Dialog to respond with the user's action. LibFileSystemAccessClient provides a lazy singleton which also ensures that FileSystemAccessServer is running in the event of a crash. This also transitions TextEditor into using LibFileSystemAccessClient.
Diffstat (limited to 'Userland/Services/FileSystemAccessServer')
-rw-r--r--Userland/Services/FileSystemAccessServer/CMakeLists.txt1
-rw-r--r--Userland/Services/FileSystemAccessServer/ClientConnection.cpp87
-rw-r--r--Userland/Services/FileSystemAccessServer/ClientConnection.h11
-rw-r--r--Userland/Services/FileSystemAccessServer/FileSystemAccessClient.ipc1
-rw-r--r--Userland/Services/FileSystemAccessServer/FileSystemAccessServer.ipc6
5 files changed, 64 insertions, 42 deletions
diff --git a/Userland/Services/FileSystemAccessServer/CMakeLists.txt b/Userland/Services/FileSystemAccessServer/CMakeLists.txt
index 67eeacb84a..9bcce5ee1a 100644
--- a/Userland/Services/FileSystemAccessServer/CMakeLists.txt
+++ b/Userland/Services/FileSystemAccessServer/CMakeLists.txt
@@ -16,3 +16,4 @@ set(SOURCES
serenity_bin(FileSystemAccessServer)
target_link_libraries(FileSystemAccessServer LibCore LibIPC LibGUI)
+add_dependencies(FileSystemAccessServer WindowServer)
diff --git a/Userland/Services/FileSystemAccessServer/ClientConnection.cpp b/Userland/Services/FileSystemAccessServer/ClientConnection.cpp
index d863a22c47..aaa2e78055 100644
--- a/Userland/Services/FileSystemAccessServer/ClientConnection.cpp
+++ b/Userland/Services/FileSystemAccessServer/ClientConnection.cpp
@@ -4,6 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+// FIXME: LibIPC Decoder and Encoder are sensitive to include order here
+// clang-format off
+#include <LibGUI/WindowServerConnection.h>
+// clang-format on
#include <AK/Debug.h>
#include <FileSystemAccessServer/ClientConnection.h>
#include <LibCore/File.h>
@@ -33,7 +37,20 @@ void ClientConnection::die()
exit(0);
}
-Messages::FileSystemAccessServer::RequestFileResponse ClientConnection::request_file(String const& path, Core::OpenMode const& requested_access)
+RefPtr<GUI::Window> ClientConnection::create_dummy_child_window(i32 window_server_client_id, i32 parent_window_id)
+{
+ auto window = GUI::Window::construct();
+ window->set_opacity(0);
+ window->set_frameless(true);
+ auto rect = GUI::WindowServerConnection::the().get_window_rect_from_client(window_server_client_id, parent_window_id);
+ window->set_rect(rect);
+ window->show();
+ GUI::WindowServerConnection::the().async_set_window_parent_from_client(window_server_client_id, parent_window_id, window->window_id());
+
+ return window;
+}
+
+void ClientConnection::request_file(i32 window_server_client_id, i32 parent_window_id, String const& path, Core::OpenMode const& requested_access)
{
VERIFY(path.starts_with("/"sv));
@@ -47,21 +64,23 @@ Messages::FileSystemAccessServer::RequestFileResponse ClientConnection::request_
approved = has_flag(maybe_permissions.value(), relevant_permissions);
if (!approved) {
- StringBuilder builder;
- if (has_flag(requested_access, Core::OpenMode::ReadOnly))
- builder.append('r');
-
- if (has_flag(requested_access, Core::OpenMode::WriteOnly))
- builder.append('w');
+ String access_string;
- auto access_string = builder.to_string();
+ if (has_flag(requested_access, Core::OpenMode::ReadWrite))
+ access_string = "read and write";
+ else if (has_flag(requested_access, Core::OpenMode::ReadOnly))
+ access_string = "read from";
+ else if (has_flag(requested_access, Core::OpenMode::WriteOnly))
+ access_string = "write to";
auto pid = this->socket().peer_pid();
auto exe_link = LexicalPath("/proc").append(String::number(pid)).append("exe").string();
auto exe_path = Core::File::real_path_for(exe_link);
auto exe_name = LexicalPath::basename(exe_path);
- auto result = GUI::MessageBox::show(nullptr, String::formatted("Give {} ({}) \"{}\" access to \"{}\"?", exe_name, pid, access_string, path), "File Permissions Requested", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::YesNo);
+ auto main_window = create_dummy_child_window(window_server_client_id, parent_window_id);
+
+ auto result = GUI::MessageBox::show(main_window, String::formatted("Allow {} ({}) to {} \"{}\"?", exe_name, pid, access_string, path), "File Permissions Requested", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::YesNo);
approved = result == GUI::MessageBox::ExecYes;
@@ -80,40 +99,40 @@ Messages::FileSystemAccessServer::RequestFileResponse ClientConnection::request_
if (file.is_error()) {
dbgln("FileSystemAccessServer: Couldn't open {}, error {}", path, file.error());
-
- return { errno, Optional<IPC::File> {} };
+ async_handle_prompt_end(errno, Optional<IPC::File> {}, path);
+ } else {
+ async_handle_prompt_end(0, IPC::File(file.value()->leak_fd(), IPC::File::CloseAfterSending), path);
}
-
- return { 0, IPC::File(file.value()->leak_fd(), IPC::File::CloseAfterSending) };
+ } else {
+ async_handle_prompt_end(-1, Optional<IPC::File> {}, path);
}
-
- return { -1, Optional<IPC::File> {} };
}
-Messages::FileSystemAccessServer::PromptOpenFileResponse ClientConnection::prompt_open_file(String const& path_to_view, Core::OpenMode const& requested_access)
+void ClientConnection::prompt_open_file(i32 window_server_client_id, i32 parent_window_id, String const& path_to_view, Core::OpenMode const& requested_access)
{
auto relevant_permissions = requested_access & (Core::OpenMode::ReadOnly | Core::OpenMode::WriteOnly);
VERIFY(relevant_permissions != Core::OpenMode::NotOpen);
- auto main_window = GUI::Window::construct();
+ auto main_window = create_dummy_child_window(window_server_client_id, parent_window_id);
+
auto user_picked_file = GUI::FilePicker::get_open_filepath(main_window, "Select file", path_to_view);
- return prompt_helper<Messages::FileSystemAccessServer::PromptOpenFileResponse>(user_picked_file, requested_access);
+ prompt_helper(user_picked_file, requested_access);
}
-Messages::FileSystemAccessServer::PromptSaveFileResponse ClientConnection::prompt_save_file(String const& name, String const& ext, String const& path_to_view, Core::OpenMode const& requested_access)
+void ClientConnection::prompt_save_file(i32 window_server_client_id, i32 parent_window_id, String const& name, String const& ext, String const& path_to_view, Core::OpenMode const& requested_access)
{
auto relevant_permissions = requested_access & (Core::OpenMode::ReadOnly | Core::OpenMode::WriteOnly);
VERIFY(relevant_permissions != Core::OpenMode::NotOpen);
- auto main_window = GUI::Window::construct();
+ auto main_window = create_dummy_child_window(window_server_client_id, parent_window_id);
+
auto user_picked_file = GUI::FilePicker::get_save_filepath(main_window, name, ext, path_to_view);
- return prompt_helper<Messages::FileSystemAccessServer::PromptSaveFileResponse>(user_picked_file, requested_access);
+ prompt_helper(user_picked_file, requested_access);
}
-template<typename T>
-T ClientConnection::prompt_helper(Optional<String> const& user_picked_file, Core::OpenMode const& requested_access)
+void ClientConnection::prompt_helper(Optional<String> const& user_picked_file, Core::OpenMode const& requested_access)
{
if (user_picked_file.has_value()) {
VERIFY(user_picked_file->starts_with("/"sv));
@@ -122,20 +141,20 @@ T ClientConnection::prompt_helper(Optional<String> const& user_picked_file, Core
if (file.is_error()) {
dbgln("FileSystemAccessServer: Couldn't open {}, error {}", user_picked_file.value(), file.error());
- return { errno, Optional<IPC::File> {}, user_picked_file.value() };
- }
-
- auto maybe_permissions = m_approved_files.get(user_picked_file.value());
- auto new_permissions = requested_access & (Core::OpenMode::ReadOnly | Core::OpenMode::WriteOnly);
- if (maybe_permissions.has_value())
- new_permissions |= maybe_permissions.value();
+ async_handle_prompt_end(errno, Optional<IPC::File> {}, user_picked_file);
+ } else {
+ auto maybe_permissions = m_approved_files.get(user_picked_file.value());
+ auto new_permissions = requested_access & (Core::OpenMode::ReadOnly | Core::OpenMode::WriteOnly);
+ if (maybe_permissions.has_value())
+ new_permissions |= maybe_permissions.value();
- m_approved_files.set(user_picked_file.value(), new_permissions);
+ m_approved_files.set(user_picked_file.value(), new_permissions);
- return { 0, IPC::File(file.value()->leak_fd(), IPC::File::CloseAfterSending), user_picked_file.value() };
+ async_handle_prompt_end(0, IPC::File(file.value()->leak_fd(), IPC::File::CloseAfterSending), user_picked_file);
+ }
+ } else {
+ async_handle_prompt_end(-1, Optional<IPC::File> {}, Optional<String> {});
}
-
- return { -1, Optional<IPC::File> {}, Optional<String> {} };
}
}
diff --git a/Userland/Services/FileSystemAccessServer/ClientConnection.h b/Userland/Services/FileSystemAccessServer/ClientConnection.h
index 2f738bb4e7..9261bc029c 100644
--- a/Userland/Services/FileSystemAccessServer/ClientConnection.h
+++ b/Userland/Services/FileSystemAccessServer/ClientConnection.h
@@ -10,6 +10,7 @@
#include <FileSystemAccessServer/FileSystemAccessClientEndpoint.h>
#include <FileSystemAccessServer/FileSystemAccessServerEndpoint.h>
#include <LibCore/Forward.h>
+#include <LibGUI/Forward.h>
#include <LibIPC/ClientConnection.h>
namespace FileSystemAccessServer {
@@ -25,12 +26,12 @@ public:
virtual void die() override;
private:
- virtual Messages::FileSystemAccessServer::RequestFileResponse request_file(String const&, Core::OpenMode const&) override;
- virtual Messages::FileSystemAccessServer::PromptOpenFileResponse prompt_open_file(String const&, Core::OpenMode const&) override;
- virtual Messages::FileSystemAccessServer::PromptSaveFileResponse prompt_save_file(String const&, String const&, String const&, Core::OpenMode const&) override;
+ virtual void request_file(i32, i32, String const&, Core::OpenMode const&) override;
+ virtual void prompt_open_file(i32, i32, String const&, Core::OpenMode const&) override;
+ virtual void prompt_save_file(i32, i32, String const&, String const&, String const&, Core::OpenMode const&) override;
- template<typename T>
- T prompt_helper(Optional<String> const&, Core::OpenMode const&);
+ void prompt_helper(Optional<String> const&, Core::OpenMode const&);
+ RefPtr<GUI::Window> create_dummy_child_window(i32, i32);
HashMap<String, Core::OpenMode> m_approved_files;
};
diff --git a/Userland/Services/FileSystemAccessServer/FileSystemAccessClient.ipc b/Userland/Services/FileSystemAccessServer/FileSystemAccessClient.ipc
index fa99132c8f..180d23304b 100644
--- a/Userland/Services/FileSystemAccessServer/FileSystemAccessClient.ipc
+++ b/Userland/Services/FileSystemAccessServer/FileSystemAccessClient.ipc
@@ -1,3 +1,4 @@
endpoint FileSystemAccessClient
{
+ handle_prompt_end(i32 error, Optional<IPC::File> fd, Optional<String> chosen_file) =|
}
diff --git a/Userland/Services/FileSystemAccessServer/FileSystemAccessServer.ipc b/Userland/Services/FileSystemAccessServer/FileSystemAccessServer.ipc
index 6f10d9ba61..15c3735d8e 100644
--- a/Userland/Services/FileSystemAccessServer/FileSystemAccessServer.ipc
+++ b/Userland/Services/FileSystemAccessServer/FileSystemAccessServer.ipc
@@ -3,7 +3,7 @@
endpoint FileSystemAccessServer
{
- request_file(String path, Core::OpenMode requested_access) => (i32 error, Optional<IPC::File> fd)
- prompt_open_file(String path_to_view, Core::OpenMode requested_access) => (i32 error, Optional<IPC::File> fd, Optional<String> chosen_file)
- prompt_save_file(String title, String ext, String path_to_view, Core::OpenMode requested_access) => (i32 error, Optional<IPC::File> fd, Optional<String> chosen_file)
+ request_file(i32 window_server_client_id, i32 window_id, String path, Core::OpenMode requested_access) =|
+ prompt_open_file(i32 window_server_client_id, i32 window_id, String path_to_view, Core::OpenMode requested_access) =|
+ prompt_save_file(i32 window_server_client_id, i32 window_id,String title, String ext, String path_to_view, Core::OpenMode requested_access) =|
}