ApplicationBridge.cpp 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Application/ApplicationBridge.h>
  7. #include <Ladybird/AppKit/UI/LadybirdWebViewBridge.h>
  8. #include <Ladybird/HelperProcess.h>
  9. #include <Ladybird/Utilities.h>
  10. #include <LibImageDecoderClient/Client.h>
  11. #include <LibProtocol/RequestClient.h>
  12. #include <LibWebView/WebContentClient.h>
  13. namespace Ladybird {
  14. // Unfortunately, the Protocol namespace conflicts hard with a @Protocol interface defined by Objective-C. And the #define
  15. // trick we use for e.g. Duration does not work for Protocol. So here, we make sure that any use of the Protocol namespace
  16. // is limited to .cpp files (i.e. not .h files that an Objective-C file can include).
  17. struct ApplicationBridgeImpl {
  18. RefPtr<Protocol::RequestClient> request_server_client;
  19. RefPtr<ImageDecoderClient::Client> image_decoder_client;
  20. };
  21. ApplicationBridge::ApplicationBridge(Badge<WebView::Application>, Main::Arguments&)
  22. : m_impl(make<ApplicationBridgeImpl>())
  23. {
  24. }
  25. ApplicationBridge::~ApplicationBridge() = default;
  26. ErrorOr<void> ApplicationBridge::launch_request_server()
  27. {
  28. auto request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
  29. auto protocol_client = TRY(launch_request_server_process(request_server_paths, s_ladybird_resource_root));
  30. m_impl->request_server_client = move(protocol_client);
  31. return {};
  32. }
  33. static ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_new_image_decoder()
  34. {
  35. auto image_decoder_paths = TRY(get_paths_for_helper_process("ImageDecoder"sv));
  36. return launch_image_decoder_process(image_decoder_paths);
  37. }
  38. ErrorOr<void> ApplicationBridge::launch_image_decoder()
  39. {
  40. m_impl->image_decoder_client = TRY(launch_new_image_decoder());
  41. m_impl->image_decoder_client->on_death = [this] {
  42. m_impl->image_decoder_client = nullptr;
  43. if (auto err = this->launch_image_decoder(); err.is_error()) {
  44. dbgln("Failed to restart image decoder: {}", err.error());
  45. VERIFY_NOT_REACHED();
  46. }
  47. auto num_clients = WebView::WebContentClient::client_count();
  48. auto new_sockets = m_impl->image_decoder_client->send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(num_clients);
  49. if (!new_sockets || new_sockets->sockets().size() == 0) {
  50. dbgln("Failed to connect {} new clients to ImageDecoder", num_clients);
  51. VERIFY_NOT_REACHED();
  52. }
  53. WebView::WebContentClient::for_each_client([sockets = new_sockets->take_sockets()](WebView::WebContentClient& client) mutable {
  54. client.async_connect_to_image_decoder(sockets.take_last());
  55. return IterationDecision::Continue;
  56. });
  57. };
  58. return {};
  59. }
  60. ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ApplicationBridge::launch_web_content(WebViewBridge& web_view_bridge)
  61. {
  62. // FIXME: Fail to open the tab, rather than crashing the whole application if this fails
  63. auto request_server_socket = TRY(connect_new_request_server_client(*m_impl->request_server_client));
  64. auto image_decoder_socket = TRY(connect_new_image_decoder_client(*m_impl->image_decoder_client));
  65. auto web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
  66. auto web_content = TRY(launch_web_content_process(web_view_bridge, web_content_paths, move(image_decoder_socket), move(request_server_socket)));
  67. return web_content;
  68. }
  69. ErrorOr<IPC::File> ApplicationBridge::launch_web_worker()
  70. {
  71. auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
  72. auto worker_client = TRY(launch_web_worker_process(web_worker_paths, m_impl->request_server_client));
  73. return worker_client->dup_socket();
  74. }
  75. }