Serenity Operating System
at master 108 lines 3.7 kB view raw
1/* 2 * Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibCore/ArgsParser.h> 8#include <LibCore/Directory.h> 9#include <LibCore/EventLoop.h> 10#include <LibCore/StandardPaths.h> 11#include <LibCore/System.h> 12#include <LibCore/TCPServer.h> 13#include <LibMain/Main.h> 14#include <WebDriver/Client.h> 15 16static ErrorOr<pid_t> launch_browser(DeprecatedString const& socket_path) 17{ 18 char const* argv[] = { 19 "/bin/Browser", 20 "--webdriver-content-path", 21 socket_path.characters(), 22 nullptr, 23 }; 24 25 return Core::System::posix_spawn("/bin/Browser"sv, nullptr, nullptr, const_cast<char**>(argv), environ); 26} 27 28static ErrorOr<pid_t> launch_headless_browser(DeprecatedString const& socket_path) 29{ 30 char const* argv[] = { 31 "/bin/headless-browser", 32 "--webdriver-ipc-path", 33 socket_path.characters(), 34 "about:blank", 35 nullptr, 36 }; 37 38 return Core::System::posix_spawn("/bin/headless-browser"sv, nullptr, nullptr, const_cast<char**>(argv), environ); 39} 40 41ErrorOr<int> serenity_main(Main::Arguments arguments) 42{ 43 DeprecatedString default_listen_address = "0.0.0.0"; 44 u16 default_port = 8000; 45 46 DeprecatedString listen_address = default_listen_address; 47 int port = default_port; 48 49 Core::ArgsParser args_parser; 50 args_parser.add_option(listen_address, "IP address to listen on", "listen-address", 'l', "listen_address"); 51 args_parser.add_option(port, "Port to listen on", "port", 'p', "port"); 52 args_parser.parse(arguments); 53 54 auto ipv4_address = IPv4Address::from_string(listen_address); 55 if (!ipv4_address.has_value()) { 56 warnln("Invalid listen address: {}", listen_address); 57 return 1; 58 } 59 60 if ((u16)port != port) { 61 warnln("Invalid port number: {}", port); 62 return 1; 63 } 64 65 TRY(Core::System::pledge("stdio accept cpath rpath recvfd inet unix proc exec fattr")); 66 67 auto webdriver_socket_path = DeprecatedString::formatted("{}/webdriver", TRY(Core::StandardPaths::runtime_directory())); 68 TRY(Core::Directory::create(webdriver_socket_path, Core::Directory::CreateDirectories::Yes)); 69 70 Core::EventLoop loop; 71 72 auto server = TRY(Core::TCPServer::try_create()); 73 74 // FIXME: Propagate errors 75 server->on_ready_to_accept = [&] { 76 auto maybe_client_socket = server->accept(); 77 if (maybe_client_socket.is_error()) { 78 warnln("Failed to accept the client: {}", maybe_client_socket.error()); 79 return; 80 } 81 82 auto maybe_buffered_socket = Core::BufferedTCPSocket::create(maybe_client_socket.release_value()); 83 if (maybe_buffered_socket.is_error()) { 84 warnln("Could not obtain a buffered socket for the client: {}", maybe_buffered_socket.error()); 85 return; 86 } 87 88 auto maybe_client = WebDriver::Client::try_create(maybe_buffered_socket.release_value(), { launch_browser, launch_headless_browser }, server); 89 if (maybe_client.is_error()) { 90 warnln("Could not create a WebDriver client: {}", maybe_client.error()); 91 return; 92 } 93 }; 94 95 TRY(server->listen(ipv4_address.value(), port)); 96 97 outln("Listening on {}:{}", ipv4_address.value(), port); 98 99 TRY(Core::System::unveil("/bin/Browser", "rx")); 100 TRY(Core::System::unveil("/bin/headless-browser", "rx")); 101 TRY(Core::System::unveil("/etc/timezone", "r")); 102 TRY(Core::System::unveil("/res/icons", "r")); 103 TRY(Core::System::unveil(webdriver_socket_path, "rwc"sv)); 104 TRY(Core::System::unveil(nullptr, nullptr)); 105 106 TRY(Core::System::pledge("stdio accept cpath rpath recvfd unix proc exec fattr")); 107 return loop.exec(); 108}