From 57e0a3f8b5e581ef91880b57bf1d1c80d5a17f2c Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Thu, 6 Mar 2025 19:56:40 -0500 Subject: [PATCH] LibDevTools+LibWebView: Implement requests to edit DOM node text --- Libraries/LibDevTools/Actors/NodeActor.cpp | 37 +++++++++++++++++++++- Libraries/LibDevTools/Actors/NodeActor.h | 2 ++ Libraries/LibDevTools/DevToolsDelegate.h | 3 ++ Libraries/LibWebView/Application.cpp | 28 ++++++++++++++++ Libraries/LibWebView/Application.h | 1 + 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Libraries/LibDevTools/Actors/NodeActor.cpp b/Libraries/LibDevTools/Actors/NodeActor.cpp index 1c9869e6e3f..a0021903bbb 100644 --- a/Libraries/LibDevTools/Actors/NodeActor.cpp +++ b/Libraries/LibDevTools/Actors/NodeActor.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include namespace DevTools { @@ -42,7 +44,7 @@ NodeActor::NodeActor(DevToolsServer& devtools, String name, NodeIdentifier node_ NodeActor::~NodeActor() = default; -void NodeActor::handle_message(StringView type, JsonObject const&) +void NodeActor::handle_message(StringView type, JsonObject const& message) { JsonObject response; response.set("from"sv, name()); @@ -55,7 +57,40 @@ void NodeActor::handle_message(StringView type, JsonObject const&) return; } + if (type == "setNodeValue"sv) { + auto value = message.get_string("value"sv); + if (!value.has_value()) { + send_missing_parameter_error("value"sv); + return; + } + + if (auto dom_node = WalkerActor::dom_node_for(m_walker, name()); dom_node.has_value()) { + auto block_token = block_responses(); + + devtools().delegate().set_dom_node_text( + dom_node->tab->description(), dom_node->identifier.id, value.release_value(), + [weak_self = make_weak_ptr(), block_token = move(block_token)](ErrorOr node_id) mutable { + if (node_id.is_error()) { + dbgln_if(DEVTOOLS_DEBUG, "Unable to edit DOM node: {}", node_id.error()); + return; + } + + if (auto self = weak_self.strong_ref()) + self->finished_editing_dom_node(move(block_token)); + }); + } + + return; + } + send_unrecognized_packet_type_error(type); } +void NodeActor::finished_editing_dom_node(BlockToken block_token) +{ + JsonObject message; + message.set("from"sv, name()); + send_message(move(message), move(block_token)); +} + } diff --git a/Libraries/LibDevTools/Actors/NodeActor.h b/Libraries/LibDevTools/Actors/NodeActor.h index 71cc1a52378..09c828e2f8f 100644 --- a/Libraries/LibDevTools/Actors/NodeActor.h +++ b/Libraries/LibDevTools/Actors/NodeActor.h @@ -36,6 +36,8 @@ public: private: NodeActor(DevToolsServer&, String name, NodeIdentifier, WeakPtr); + void finished_editing_dom_node(BlockToken); + NodeIdentifier m_node_identifier; WeakPtr m_walker; diff --git a/Libraries/LibDevTools/DevToolsDelegate.h b/Libraries/LibDevTools/DevToolsDelegate.h index 83da6431b4e..4ec995e73c2 100644 --- a/Libraries/LibDevTools/DevToolsDelegate.h +++ b/Libraries/LibDevTools/DevToolsDelegate.h @@ -41,6 +41,9 @@ public: virtual void listen_for_dom_mutations(TabDescription const&, OnDOMMutationReceived) const { } virtual void stop_listening_for_dom_mutations(TabDescription const&) const { } + using OnDOMNodeEditComplete = Function)>; + virtual void set_dom_node_text(TabDescription const&, Web::UniqueNodeID, String, OnDOMNodeEditComplete) const { } + using OnScriptEvaluationComplete = Function)>; virtual void evaluate_javascript(TabDescription const&, String, OnScriptEvaluationComplete) const { } diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index 084c87821f2..744daab7a78 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -437,6 +437,34 @@ void Application::stop_listening_for_dom_mutations(DevTools::TabDescription cons view->set_listen_for_dom_mutations(false); } +template +static void edit_dom_node(DevTools::TabDescription const& description, Application::OnDOMNodeEditComplete on_complete, Edit&& edit) +{ + auto view = ViewImplementation::find_view_by_id(description.id); + if (!view.has_value()) { + on_complete(Error::from_string_literal("Unable to locate tab")); + return; + } + + view->on_finshed_editing_dom_node = [&view = *view, on_complete = move(on_complete)](auto node_id) { + view.on_finshed_editing_dom_node = nullptr; + + if (node_id.has_value()) + on_complete(*node_id); + else + on_complete(Error::from_string_literal("Unable to find DOM node to edit")); + }; + + edit(*view); +} + +void Application::set_dom_node_text(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, String value, OnDOMNodeEditComplete on_complete) const +{ + edit_dom_node(description, move(on_complete), [&](auto& view) { + view.set_dom_node_text(node_id, move(value)); + }); +} + void Application::evaluate_javascript(DevTools::TabDescription const& description, String script, OnScriptEvaluationComplete on_complete) const { auto view = ViewImplementation::find_view_by_id(description.id); diff --git a/Libraries/LibWebView/Application.h b/Libraries/LibWebView/Application.h index fa3adb6531c..195d2a9fb0c 100644 --- a/Libraries/LibWebView/Application.h +++ b/Libraries/LibWebView/Application.h @@ -98,6 +98,7 @@ private: virtual void clear_highlighted_dom_node(DevTools::TabDescription const&) const override; virtual void listen_for_dom_mutations(DevTools::TabDescription const&, OnDOMMutationReceived) const override; virtual void stop_listening_for_dom_mutations(DevTools::TabDescription const&) const override; + virtual void set_dom_node_text(DevTools::TabDescription const&, Web::UniqueNodeID, String, OnDOMNodeEditComplete) const override; virtual void evaluate_javascript(DevTools::TabDescription const&, String, OnScriptEvaluationComplete) const override; virtual void listen_for_console_messages(DevTools::TabDescription const&, OnConsoleMessageAvailable, OnReceivedConsoleMessages) const override; virtual void stop_listening_for_console_messages(DevTools::TabDescription const&) const override;