mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Userland: Add try_* IPC handlers
This enables calling auto-generated IPC methods in a way that doesn't crash the client if the peer disconnects.
This commit is contained in:
parent
34cf5cf07f
commit
8a6db55e79
Notes:
sideshowbarker
2024-07-18 18:44:19 +09:00
Author: https://github.com/gunnarbeutner Commit: https://github.com/SerenityOS/serenity/commit/8a6db55e79e
4 changed files with 62 additions and 27 deletions
|
@ -247,6 +247,7 @@ int main(int argc, char** argv)
|
|||
#pragma once
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/Result.h>
|
||||
#include <AK/URL.h>
|
||||
#include <AK/Utf8View.h>
|
||||
#include <LibCore/AnonymousBuffer.h>
|
||||
|
@ -496,7 +497,7 @@ public:
|
|||
for (auto& message : endpoint.messages) {
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
|
||||
auto do_implement_proxy = [&](String const& name, Vector<Parameter> const& parameters, bool is_synchronous) {
|
||||
auto do_implement_proxy = [&](String const& name, Vector<Parameter> const& parameters, bool is_synchronous, bool is_try) {
|
||||
String return_type = "void";
|
||||
if (is_synchronous) {
|
||||
if (message.outputs.size() == 1)
|
||||
|
@ -504,14 +505,23 @@ public:
|
|||
else if (!message.outputs.is_empty())
|
||||
return_type = message_name(endpoint.name, message.name, true);
|
||||
}
|
||||
String inner_return_type = return_type;
|
||||
if (is_try) {
|
||||
StringBuilder builder;
|
||||
builder.append("Result<");
|
||||
builder.append(return_type);
|
||||
builder.append(", IPC::ErrorCode>");
|
||||
return_type = builder.to_string();
|
||||
}
|
||||
message_generator.set("message.name", message.name);
|
||||
message_generator.set("message.pascal_name", pascal_case(message.name));
|
||||
message_generator.set("message.complex_return_type", return_type);
|
||||
message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_");
|
||||
message_generator.set("try_prefix_maybe", is_try ? "try_" : "");
|
||||
|
||||
message_generator.set("handler_name", name);
|
||||
message_generator.append(R"~~~(
|
||||
@message.complex_return_type@ @async_prefix_maybe@@handler_name@()~~~");
|
||||
@message.complex_return_type@ @try_prefix_maybe@@async_prefix_maybe@@handler_name@()~~~");
|
||||
|
||||
for (size_t i = 0; i < parameters.size(); ++i) {
|
||||
auto& parameter = parameters[i];
|
||||
|
@ -525,18 +535,21 @@ public:
|
|||
|
||||
message_generator.append(") {");
|
||||
|
||||
if (is_synchronous) {
|
||||
if (is_synchronous && !is_try) {
|
||||
if (return_type != "void") {
|
||||
message_generator.append(R"~~~(
|
||||
return )~~~");
|
||||
if (message.outputs.size() != 1)
|
||||
message_generator.append(" move(*");
|
||||
message_generator.append("move(*");
|
||||
} else {
|
||||
message_generator.append(R"~~~(
|
||||
)~~~");
|
||||
}
|
||||
|
||||
message_generator.append("m_connection.template send_sync<Messages::@endpoint.name@::@message.pascal_name@>(");
|
||||
} else if (is_try) {
|
||||
message_generator.append(R"~~~(
|
||||
auto result = m_connection.template send_sync_but_allow_failure<Messages::@endpoint.name@::@message.pascal_name@>()~~~");
|
||||
} else {
|
||||
message_generator.append(R"~~~(
|
||||
m_connection.post_message(Messages::@endpoint.name@::@message.pascal_name@ { )~~~");
|
||||
|
@ -554,7 +567,7 @@ public:
|
|||
argument_generator.append(", ");
|
||||
}
|
||||
|
||||
if (is_synchronous) {
|
||||
if (is_synchronous && !is_try) {
|
||||
if (return_type != "void") {
|
||||
message_generator.append(")");
|
||||
}
|
||||
|
@ -566,20 +579,36 @@ public:
|
|||
} else
|
||||
message_generator.append(")");
|
||||
|
||||
message_generator.append(R"~~~(;
|
||||
}
|
||||
message_generator.append(";");
|
||||
} else if (is_try) {
|
||||
message_generator.append(R"~~~();
|
||||
if (!result)
|
||||
return IPC::ErrorCode::PeerDisconnected;
|
||||
)~~~");
|
||||
|
||||
if (inner_return_type != "void") {
|
||||
message_generator.append(R"~~~(
|
||||
return move(*result);
|
||||
)~~~");
|
||||
} else {
|
||||
message_generator.append(R"~~~(
|
||||
return { };
|
||||
)~~~");
|
||||
}
|
||||
} else {
|
||||
message_generator.append(R"~~~( });
|
||||
}
|
||||
)~~~");
|
||||
}
|
||||
|
||||
message_generator.append(R"~~~(
|
||||
}
|
||||
)~~~");
|
||||
};
|
||||
|
||||
do_implement_proxy(message.name, message.inputs, message.is_synchronous);
|
||||
if (message.is_synchronous)
|
||||
do_implement_proxy(message.name, message.inputs, false);
|
||||
do_implement_proxy(message.name, message.inputs, message.is_synchronous, false);
|
||||
if (message.is_synchronous) {
|
||||
do_implement_proxy(message.name, message.inputs, false, false);
|
||||
do_implement_proxy(message.name, message.inputs, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
endpoint_generator.append(R"~~~(
|
||||
|
|
|
@ -59,8 +59,8 @@ static LaunchServerConnection& connection()
|
|||
|
||||
bool Launcher::add_allowed_url(const URL& url)
|
||||
{
|
||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedUrl>(url);
|
||||
if (!response) {
|
||||
auto response_or_error = connection().try_add_allowed_url(url);
|
||||
if (response_or_error.is_error()) {
|
||||
dbgln("Launcher::add_allowed_url: Failed");
|
||||
return false;
|
||||
}
|
||||
|
@ -69,8 +69,8 @@ bool Launcher::add_allowed_url(const URL& url)
|
|||
|
||||
bool Launcher::add_allowed_handler_with_any_url(const String& handler)
|
||||
{
|
||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedHandlerWithAnyUrl>(handler);
|
||||
if (!response) {
|
||||
auto response_or_error = connection().try_add_allowed_handler_with_any_url(handler);
|
||||
if (response_or_error.is_error()) {
|
||||
dbgln("Launcher::add_allowed_handler_with_any_url: Failed");
|
||||
return false;
|
||||
}
|
||||
|
@ -79,8 +79,8 @@ bool Launcher::add_allowed_handler_with_any_url(const String& handler)
|
|||
|
||||
bool Launcher::add_allowed_handler_with_only_specific_urls(const String& handler, const Vector<URL>& urls)
|
||||
{
|
||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::AddAllowedHandlerWithOnlySpecificUrls>(handler, urls);
|
||||
if (!response) {
|
||||
auto response_or_error = connection().try_add_allowed_handler_with_only_specific_urls(handler, urls);
|
||||
if (response_or_error.is_error()) {
|
||||
dbgln("Launcher::add_allowed_handler_with_only_specific_urls: Failed");
|
||||
return false;
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ bool Launcher::add_allowed_handler_with_only_specific_urls(const String& handler
|
|||
|
||||
bool Launcher::seal_allowlist()
|
||||
{
|
||||
auto response = connection().send_sync_but_allow_failure<Messages::LaunchServer::SealAllowlist>();
|
||||
if (!response) {
|
||||
auto response_or_error = connection().try_seal_allowlist();
|
||||
if (response_or_error.is_error()) {
|
||||
dbgln("Launcher::seal_allowlist: Failed");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ struct MessageBuffer {
|
|||
Vector<RefPtr<AutoCloseFileDescriptor>> fds;
|
||||
};
|
||||
|
||||
enum class ErrorCode : u32 {
|
||||
PeerDisconnected
|
||||
};
|
||||
|
||||
class Message {
|
||||
public:
|
||||
virtual ~Message();
|
||||
|
|
|
@ -42,21 +42,23 @@ Optional<DecodedImage> Client::decode_image(const ByteBuffer& encoded_data)
|
|||
}
|
||||
|
||||
memcpy(encoded_buffer.data<void>(), encoded_data.data(), encoded_data.size());
|
||||
auto response = send_sync_but_allow_failure<Messages::ImageDecoderServer::DecodeImage>(move(encoded_buffer));
|
||||
auto response_or_error = try_decode_image(move(encoded_buffer));
|
||||
|
||||
if (!response) {
|
||||
if (response_or_error.is_error()) {
|
||||
dbgln("ImageDecoder died heroically");
|
||||
return {};
|
||||
}
|
||||
|
||||
auto& response = response_or_error.value();
|
||||
|
||||
DecodedImage image;
|
||||
image.is_animated = response->is_animated();
|
||||
image.loop_count = response->loop_count();
|
||||
image.frames.resize(response->bitmaps().size());
|
||||
image.is_animated = response.is_animated();
|
||||
image.loop_count = response.loop_count();
|
||||
image.frames.resize(response.bitmaps().size());
|
||||
for (size_t i = 0; i < image.frames.size(); ++i) {
|
||||
auto& frame = image.frames[i];
|
||||
frame.bitmap = response->bitmaps()[i].bitmap();
|
||||
frame.duration = response->durations()[i];
|
||||
frame.bitmap = response.bitmaps()[i].bitmap();
|
||||
frame.duration = response.durations()[i];
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue