mirror of
				https://github.com/LadybirdBrowser/ladybird.git
				synced 2025-11-01 05:41:01 +00:00 
			
		
		
		
	 58bc44ba2a
			
		
	
	
		58bc44ba2a
		
	
	
	
	
		
			
			To aid with debugging web page issues in Ladybird without needing to implement a fully fledged inspector, we can implement the Firefox DevTools protocol and use their DevTools. The protocol is described here: https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html This commit contains just enough to connect to Ladybird from a DevTools client.
		
			
				
	
	
		
			107 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/Debug.h>
 | |
| #include <AK/JsonObject.h>
 | |
| #include <AK/JsonValue.h>
 | |
| #include <LibCore/EventLoop.h>
 | |
| #include <LibCore/Socket.h>
 | |
| #include <LibCore/TCPServer.h>
 | |
| #include <LibDevTools/Actors/DeviceActor.h>
 | |
| #include <LibDevTools/Actors/PreferenceActor.h>
 | |
| #include <LibDevTools/Actors/ProcessActor.h>
 | |
| #include <LibDevTools/Connection.h>
 | |
| #include <LibDevTools/DevToolsServer.h>
 | |
| 
 | |
| namespace DevTools {
 | |
| 
 | |
| static u64 s_server_count = 0;
 | |
| 
 | |
| ErrorOr<NonnullOwnPtr<DevToolsServer>> DevToolsServer::create(DevToolsDelegate& delegate, u16 port)
 | |
| {
 | |
|     auto address = IPv4Address::from_string("0.0.0.0"sv).release_value();
 | |
| 
 | |
|     auto server = TRY(Core::TCPServer::try_create());
 | |
|     TRY(server->listen(address, port, Core::TCPServer::AllowAddressReuse::Yes));
 | |
| 
 | |
|     return adopt_own(*new DevToolsServer(delegate, move(server)));
 | |
| }
 | |
| 
 | |
| DevToolsServer::DevToolsServer(DevToolsDelegate& delegate, NonnullRefPtr<Core::TCPServer> server)
 | |
|     : m_server(move(server))
 | |
|     , m_delegate(delegate)
 | |
|     , m_server_id(s_server_count++)
 | |
| {
 | |
|     m_server->on_ready_to_accept = [this]() {
 | |
|         if (auto result = on_new_client(); result.is_error())
 | |
|             warnln("Failed to accept DevTools client: {}", result.error());
 | |
|     };
 | |
| }
 | |
| 
 | |
| DevToolsServer::~DevToolsServer() = default;
 | |
| 
 | |
| ErrorOr<void> DevToolsServer::on_new_client()
 | |
| {
 | |
|     if (m_connection)
 | |
|         return Error::from_string_literal("Only one active DevTools connection is currently allowed");
 | |
| 
 | |
|     auto client = TRY(m_server->accept());
 | |
|     auto buffered_socket = TRY(Core::BufferedTCPSocket::create(move(client)));
 | |
| 
 | |
|     m_connection = Connection::create(move(buffered_socket));
 | |
| 
 | |
|     m_connection->on_connection_closed = [this]() {
 | |
|         close_connection();
 | |
|     };
 | |
| 
 | |
|     m_connection->on_message_received = [this](auto const& message) {
 | |
|         on_message_received(message);
 | |
|     };
 | |
| 
 | |
|     m_root_actor = register_actor<RootActor>();
 | |
| 
 | |
|     register_actor<DeviceActor>();
 | |
|     register_actor<PreferenceActor>();
 | |
|     register_actor<ProcessActor>(ProcessDescription { .is_parent = true });
 | |
| 
 | |
|     return {};
 | |
| }
 | |
| 
 | |
| void DevToolsServer::on_message_received(JsonObject const& message)
 | |
| {
 | |
|     auto to = message.get_byte_string("to"sv);
 | |
|     if (!to.has_value()) {
 | |
|         m_root_actor->send_missing_parameter_error("to"sv);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     auto actor = m_actor_registry.find(*to);
 | |
|     if (actor == m_actor_registry.end()) {
 | |
|         m_root_actor->send_unknown_actor_error(*to);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     auto type = message.get_byte_string("type"sv);
 | |
|     if (!type.has_value()) {
 | |
|         actor->value->send_missing_parameter_error("type"sv);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     actor->value->handle_message(*type, message);
 | |
| }
 | |
| 
 | |
| void DevToolsServer::close_connection()
 | |
| {
 | |
|     dbgln_if(DEVTOOLS_DEBUG, "Lost connection to the DevTools client");
 | |
| 
 | |
|     Core::deferred_invoke([this]() {
 | |
|         m_connection = nullptr;
 | |
|         m_actor_registry.clear();
 | |
|         m_root_actor = nullptr;
 | |
|     });
 | |
| }
 | |
| 
 | |
| }
 |