1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:24:57 +00:00

FileSystemAccessClient: Add try_* variants returning Core::File

The current implementation is a bit of a hack since we also want to keep
around the previous variants for now, but will be cleaned up later once
all applications have been ported to the new API.
This commit is contained in:
Mustafa Quraish 2022-01-16 01:56:38 -05:00 committed by Andreas Kling
parent 94f2508519
commit 0c98e553e8
2 changed files with 144 additions and 5 deletions

View file

@ -11,6 +11,7 @@
#include <AK/LexicalPath.h>
#include <LibCore/File.h>
#include <LibFileSystemAccessClient/Client.h>
#include <LibGUI/MessageBox.h>
#include <LibGUI/Window.h>
namespace FileSystemAccessClient {
@ -102,15 +103,143 @@ Result Client::save_file(i32 parent_window_id, String const& name, String const
return m_promise->await();
}
void Client::handle_prompt_end(i32 error, Optional<IPC::File> const& fd, Optional<String> const& chosen_file)
FileResult Client::try_request_file_read_only_approved(GUI::Window* parent_window, String const& path)
{
VERIFY(m_promise);
m_file_promise = Core::Promise<FileResult>::construct();
m_promise = nullptr;
m_parent_window = parent_window;
if (error == 0) {
m_promise->resolve({ error, fd->take_fd(), *chosen_file });
auto parent_window_server_client_id = GUI::WindowServerConnection::the().expose_client_id();
auto child_window_server_client_id = expose_window_server_client_id();
auto parent_window_id = parent_window->window_id();
GUI::WindowServerConnection::the().async_add_window_stealing_for_client(child_window_server_client_id, parent_window_id);
ScopeGuard guard([parent_window_id, child_window_server_client_id] {
GUI::WindowServerConnection::the().async_remove_window_stealing_for_client(child_window_server_client_id, parent_window_id);
});
if (path.starts_with('/')) {
async_request_file_read_only_approved(parent_window_server_client_id, parent_window_id, path);
} else {
m_promise->resolve({ error, {}, chosen_file });
auto full_path = LexicalPath::join(Core::File::current_working_directory(), path).string();
async_request_file_read_only_approved(parent_window_server_client_id, parent_window_id, full_path);
}
return m_file_promise->await();
}
FileResult Client::try_request_file(GUI::Window* parent_window, String const& path, Core::OpenMode mode)
{
m_file_promise = Core::Promise<FileResult>::construct();
m_promise = nullptr;
m_parent_window = parent_window;
auto parent_window_server_client_id = GUI::WindowServerConnection::the().expose_client_id();
auto child_window_server_client_id = expose_window_server_client_id();
auto parent_window_id = parent_window->window_id();
GUI::WindowServerConnection::the().async_add_window_stealing_for_client(child_window_server_client_id, parent_window_id);
ScopeGuard guard([parent_window_id, child_window_server_client_id] {
GUI::WindowServerConnection::the().async_remove_window_stealing_for_client(child_window_server_client_id, parent_window_id);
});
if (path.starts_with('/')) {
async_request_file(parent_window_server_client_id, parent_window_id, path, mode);
} else {
auto full_path = LexicalPath::join(Core::File::current_working_directory(), path).string();
async_request_file(parent_window_server_client_id, parent_window_id, full_path, mode);
}
return m_file_promise->await();
}
FileResult Client::try_open_file(GUI::Window* parent_window, String const& window_title, StringView path, Core::OpenMode requested_access)
{
m_file_promise = Core::Promise<FileResult>::construct();
m_promise = nullptr;
m_parent_window = parent_window;
auto parent_window_server_client_id = GUI::WindowServerConnection::the().expose_client_id();
auto child_window_server_client_id = expose_window_server_client_id();
auto parent_window_id = parent_window->window_id();
GUI::WindowServerConnection::the().async_add_window_stealing_for_client(child_window_server_client_id, parent_window_id);
ScopeGuard guard([parent_window_id, child_window_server_client_id] {
GUI::WindowServerConnection::the().async_remove_window_stealing_for_client(child_window_server_client_id, parent_window_id);
});
async_prompt_open_file(parent_window_server_client_id, parent_window_id, window_title, path, requested_access);
return m_file_promise->await();
}
FileResult Client::try_save_file(GUI::Window* parent_window, String const& name, String const ext, Core::OpenMode requested_access)
{
m_file_promise = Core::Promise<FileResult>::construct();
m_promise = nullptr;
m_parent_window = parent_window;
auto parent_window_server_client_id = GUI::WindowServerConnection::the().expose_client_id();
auto child_window_server_client_id = expose_window_server_client_id();
auto parent_window_id = parent_window->window_id();
GUI::WindowServerConnection::the().async_add_window_stealing_for_client(child_window_server_client_id, parent_window_id);
ScopeGuard guard([parent_window_id, child_window_server_client_id] {
GUI::WindowServerConnection::the().async_remove_window_stealing_for_client(child_window_server_client_id, parent_window_id);
});
async_prompt_save_file(parent_window_server_client_id, parent_window_id, name.is_null() ? "Untitled" : name, ext.is_null() ? "txt" : ext, Core::StandardPaths::home_directory(), requested_access);
return m_file_promise->await();
}
void Client::handle_prompt_end(i32 error, Optional<IPC::File> const& ipc_file, Optional<String> const& chosen_file)
{
if (m_promise) {
if (error == 0) {
m_promise->resolve({ error, ipc_file->take_fd(), *chosen_file });
} else {
m_promise->resolve({ error, {}, chosen_file });
}
return;
}
VERIFY(m_file_promise);
if (error != 0) {
// We don't want to show an error message for non-existent files since some applications may want
// to handle it as opening a new, named file.
if (error != -1 && error != ENOENT)
GUI::MessageBox::show_error(m_parent_window, String::formatted("Opening \"{}\" failed: {}", *chosen_file, strerror(error)));
m_file_promise->resolve(Error::from_errno(error));
return;
}
auto file = Core::File::construct();
auto fd = ipc_file->take_fd();
if (!file->open(fd, Core::OpenMode::ReadWrite, Core::File::ShouldCloseFileDescriptor::Yes) && file->error() != ENOENT) {
GUI::MessageBox::show_error(m_parent_window, String::formatted("Opening \"{}\" failed: {}", *chosen_file, strerror(error)));
m_file_promise->resolve(Error::from_errno(file->error()));
return;
}
if (file->is_device()) {
GUI::MessageBox::show_error(m_parent_window, String::formatted("Opening \"{}\" failed: Cannot open device files", *chosen_file));
m_file_promise->resolve(Error::from_string_literal("Cannot open device files"sv));
return;
}
if (file->is_directory()) {
GUI::MessageBox::show_error(m_parent_window, String::formatted("Opening \"{}\" failed: Cannot open directory", *chosen_file));
m_file_promise->resolve(Error::from_string_literal("Cannot open directory"sv));
return;
}
file->set_filename(move(*chosen_file));
m_file_promise->resolve(file);
}
void Client::die()

View file

@ -11,6 +11,7 @@
#include <LibCore/File.h>
#include <LibCore/Promise.h>
#include <LibCore/StandardPaths.h>
#include <LibGUI/Window.h>
#include <LibIPC/ServerConnection.h>
namespace FileSystemAccessClient {
@ -21,6 +22,8 @@ struct Result {
Optional<String> chosen_file;
};
using FileResult = ErrorOr<NonnullRefPtr<Core::File>>;
class Client final
: public IPC::ServerConnection<FileSystemAccessClientEndpoint, FileSystemAccessServerEndpoint>
, public FileSystemAccessClientEndpoint {
@ -32,6 +35,11 @@ public:
Result open_file(i32 parent_window_id, String const& window_title = {}, StringView path = Core::StandardPaths::home_directory(), Core::OpenMode requested_access = Core::OpenMode::ReadOnly);
Result save_file(i32 parent_window_id, String const& name, String const ext, Core::OpenMode requested_access = Core::OpenMode::WriteOnly | Core::OpenMode::Truncate);
FileResult try_request_file_read_only_approved(GUI::Window* parent_window, String const& path);
FileResult try_request_file(GUI::Window* parent_window, String const& path, Core::OpenMode mode);
FileResult try_open_file(GUI::Window* parent_window, String const& window_title = {}, StringView path = Core::StandardPaths::home_directory(), Core::OpenMode requested_access = Core::OpenMode::ReadOnly);
FileResult try_save_file(GUI::Window* parent_window, String const& name, String const ext, Core::OpenMode requested_access = Core::OpenMode::WriteOnly | Core::OpenMode::Truncate);
static Client& the();
protected:
@ -46,6 +54,8 @@ private:
virtual void handle_prompt_end(i32 error, Optional<IPC::File> const& fd, Optional<String> const& chosen_file) override;
RefPtr<Core::Promise<Result>> m_promise;
RefPtr<Core::Promise<FileResult>> m_file_promise;
GUI::Window* m_parent_window { nullptr };
};
}