UI/AppKit: Remove workaround for Protocol naming conflict

The AppKit Application class is responsible for launching all helper
processes. This had to be moved to a .cpp file because we were unable to
include headers with the Protocol namespace in .mm files, as they would
conflict with the Protocol interface defined by Apple.

Now that this namespace has been renamed to Requests, we can remove this
workaround.
This commit is contained in:
Timothy Flynn
2024-08-19 19:17:49 -04:00
committed by Andreas Kling
parent 3ec5c1941f
commit a46edc2f8b
4 changed files with 75 additions and 143 deletions

View File

@@ -4,10 +4,15 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <Application/ApplicationBridge.h> #include <Ladybird/HelperProcess.h>
#include <Ladybird/Utilities.h>
#include <LibCore/EventLoop.h> #include <LibCore/EventLoop.h>
#include <LibCore/ThreadEventQueue.h> #include <LibCore/ThreadEventQueue.h>
#include <LibImageDecoderClient/Client.h>
#include <LibRequests/RequestClient.h>
#include <LibWebView/Application.h>
#include <LibWebView/WebContentClient.h> #include <LibWebView/WebContentClient.h>
#include <UI/LadybirdWebViewBridge.h>
#import <Application/Application.h> #import <Application/Application.h>
@@ -15,9 +20,24 @@
# error "This project requires ARC" # error "This project requires ARC"
#endif #endif
namespace Ladybird {
class ApplicationBridge : public WebView::Application {
WEB_VIEW_APPLICATION(ApplicationBridge)
};
ApplicationBridge::ApplicationBridge(Badge<WebView::Application>, Main::Arguments&)
{
}
}
@interface Application () @interface Application ()
{ {
OwnPtr<Ladybird::ApplicationBridge> m_application_bridge; OwnPtr<Ladybird::ApplicationBridge> m_application_bridge;
RefPtr<Requests::RequestClient> m_request_server_client;
RefPtr<ImageDecoderClient::Client> m_image_decoder_client;
} }
@end @end
@@ -34,27 +54,76 @@
- (ErrorOr<void>)launchRequestServer - (ErrorOr<void>)launchRequestServer
{ {
return m_application_bridge->launch_request_server(); auto request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
m_request_server_client = TRY(launch_request_server_process(request_server_paths, s_ladybird_resource_root));
return {};
}
static ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_new_image_decoder()
{
auto image_decoder_paths = TRY(get_paths_for_helper_process("ImageDecoder"sv));
return launch_image_decoder_process(image_decoder_paths);
} }
- (ErrorOr<void>)launchImageDecoder - (ErrorOr<void>)launchImageDecoder
{ {
return m_application_bridge->launch_image_decoder(); m_image_decoder_client = TRY(launch_new_image_decoder());
__weak Application* weak_self = self;
m_image_decoder_client->on_death = [weak_self]() {
Application* self = weak_self;
if (self == nil) {
return;
}
m_image_decoder_client = nullptr;
if (auto err = [self launchImageDecoder]; err.is_error()) {
dbgln("Failed to restart image decoder: {}", err.error());
VERIFY_NOT_REACHED();
}
auto num_clients = WebView::WebContentClient::client_count();
auto new_sockets = m_image_decoder_client->send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(num_clients);
if (!new_sockets || new_sockets->sockets().size() == 0) {
dbgln("Failed to connect {} new clients to ImageDecoder", num_clients);
VERIFY_NOT_REACHED();
}
WebView::WebContentClient::for_each_client([sockets = new_sockets->take_sockets()](WebView::WebContentClient& client) mutable {
client.async_connect_to_image_decoder(sockets.take_last());
return IterationDecision::Continue;
});
};
return {};
} }
- (ErrorOr<NonnullRefPtr<WebView::WebContentClient>>)launchWebContent:(Ladybird::WebViewBridge&)web_view_bridge - (ErrorOr<NonnullRefPtr<WebView::WebContentClient>>)launchWebContent:(Ladybird::WebViewBridge&)web_view_bridge
{ {
return m_application_bridge->launch_web_content(web_view_bridge); // FIXME: Fail to open the tab, rather than crashing the whole application if this fails
auto request_server_socket = TRY(connect_new_request_server_client(*m_request_server_client));
auto image_decoder_socket = TRY(connect_new_image_decoder_client(*m_image_decoder_client));
auto web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
auto web_content = TRY(launch_web_content_process(web_view_bridge, web_content_paths, move(image_decoder_socket), move(request_server_socket)));
return web_content;
} }
- (ErrorOr<IPC::File>)launchWebWorker - (ErrorOr<IPC::File>)launchWebWorker
{ {
return m_application_bridge->launch_web_worker(); auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, m_request_server_client));
return worker_client->dup_socket();
} }
- (void)dumpConnectionInfo:(id)sender - (void)dumpConnectionInfo:(id)sender
{ {
m_application_bridge->dump_connection_info(); m_request_server_client->dump_connection_info();
} }
#pragma mark - NSApplication #pragma mark - NSApplication

View File

@@ -1,100 +0,0 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Application/ApplicationBridge.h>
#include <Ladybird/AppKit/UI/LadybirdWebViewBridge.h>
#include <Ladybird/HelperProcess.h>
#include <Ladybird/Utilities.h>
#include <LibImageDecoderClient/Client.h>
#include <LibRequests/RequestClient.h>
#include <LibWebView/WebContentClient.h>
namespace Ladybird {
// FIXME: LibProtocol is renamed to LibRequests, remove this workaround
// Unfortunately, the Protocol namespace conflicts hard with a @Protocol interface defined by Objective-C. And the #define
// trick we use for e.g. Duration does not work for Protocol. So here, we make sure that any use of the Protocol namespace
// is limited to .cpp files (i.e. not .h files that an Objective-C file can include).
struct ApplicationBridgeImpl {
RefPtr<Requests::RequestClient> request_server_client;
RefPtr<ImageDecoderClient::Client> image_decoder_client;
};
ApplicationBridge::ApplicationBridge(Badge<WebView::Application>, Main::Arguments&)
: m_impl(make<ApplicationBridgeImpl>())
{
}
ApplicationBridge::~ApplicationBridge() = default;
ErrorOr<void> ApplicationBridge::launch_request_server()
{
auto request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
auto protocol_client = TRY(launch_request_server_process(request_server_paths, s_ladybird_resource_root));
m_impl->request_server_client = move(protocol_client);
return {};
}
static ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_new_image_decoder()
{
auto image_decoder_paths = TRY(get_paths_for_helper_process("ImageDecoder"sv));
return launch_image_decoder_process(image_decoder_paths);
}
ErrorOr<void> ApplicationBridge::launch_image_decoder()
{
m_impl->image_decoder_client = TRY(launch_new_image_decoder());
m_impl->image_decoder_client->on_death = [this] {
m_impl->image_decoder_client = nullptr;
if (auto err = this->launch_image_decoder(); err.is_error()) {
dbgln("Failed to restart image decoder: {}", err.error());
VERIFY_NOT_REACHED();
}
auto num_clients = WebView::WebContentClient::client_count();
auto new_sockets = m_impl->image_decoder_client->send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(num_clients);
if (!new_sockets || new_sockets->sockets().size() == 0) {
dbgln("Failed to connect {} new clients to ImageDecoder", num_clients);
VERIFY_NOT_REACHED();
}
WebView::WebContentClient::for_each_client([sockets = new_sockets->take_sockets()](WebView::WebContentClient& client) mutable {
client.async_connect_to_image_decoder(sockets.take_last());
return IterationDecision::Continue;
});
};
return {};
}
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ApplicationBridge::launch_web_content(WebViewBridge& web_view_bridge)
{
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
auto request_server_socket = TRY(connect_new_request_server_client(*m_impl->request_server_client));
auto image_decoder_socket = TRY(connect_new_image_decoder_client(*m_impl->image_decoder_client));
auto web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
auto web_content = TRY(launch_web_content_process(web_view_bridge, web_content_paths, move(image_decoder_socket), move(request_server_socket)));
return web_content;
}
ErrorOr<IPC::File> ApplicationBridge::launch_web_worker()
{
auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, m_impl->request_server_client));
return worker_client->dup_socket();
}
void ApplicationBridge::dump_connection_info()
{
m_impl->request_server_client->dump_connection_info();
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/NonnullOwnPtr.h>
#include <LibIPC/Forward.h>
#include <LibWebView/Application.h>
#include <LibWebView/Forward.h>
namespace Ladybird {
struct ApplicationBridgeImpl;
class WebViewBridge;
class ApplicationBridge : public WebView::Application {
WEB_VIEW_APPLICATION(ApplicationBridge)
public:
~ApplicationBridge();
ErrorOr<void> launch_request_server();
ErrorOr<void> launch_image_decoder();
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content(WebViewBridge&);
ErrorOr<IPC::File> launch_web_worker();
void dump_connection_info();
private:
NonnullOwnPtr<ApplicationBridgeImpl> m_impl;
};
}

View File

@@ -1,7 +1,6 @@
add_library(ladybird_impl STATIC add_library(ladybird_impl STATIC
${LADYBIRD_SOURCES} ${LADYBIRD_SOURCES}
Application/Application.mm Application/Application.mm
Application/ApplicationBridge.cpp
Application/ApplicationDelegate.mm Application/ApplicationDelegate.mm
Application/EventLoopImplementation.mm Application/EventLoopImplementation.mm
UI/Event.mm UI/Event.mm