diff --git a/Libraries/LibDevTools/Actors/WalkerActor.cpp b/Libraries/LibDevTools/Actors/WalkerActor.cpp index 49f531969b1..bae525ce728 100644 --- a/Libraries/LibDevTools/Actors/WalkerActor.cpp +++ b/Libraries/LibDevTools/Actors/WalkerActor.cpp @@ -232,6 +232,53 @@ void WalkerActor::handle_message(StringView type, JsonObject const& message) return; } + if (type == "insertBefore"sv) { + auto node = message.get_string("node"sv); + if (!node.has_value()) { + send_missing_parameter_error("node"sv); + return; + } + + auto parent = message.get_string("parent"sv); + if (!parent.has_value()) { + send_missing_parameter_error("parent"sv); + return; + } + + auto dom_node = WalkerActor::dom_node_for(*this, *node); + auto parent_dom_node = WalkerActor::dom_node_for(*this, *parent); + + Optional sibling_node_id; + if (auto sibling = message.get_string("sibling"sv); sibling.has_value()) { + auto sibling_dom_node = WalkerActor::dom_node_for(*this, *sibling); + if (!sibling_dom_node.has_value()) + return; + + sibling_node_id = sibling_dom_node->identifier.id; + } + + if (dom_node.has_value() && parent_dom_node.has_value()) { + auto block_token = block_responses(); + + devtools().delegate().insert_dom_node_before( + dom_node->tab->description(), dom_node->identifier.id, parent_dom_node->identifier.id, sibling_node_id, + [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()) { + JsonObject message; + message.set("from"sv, self->name()); + self->send_message(move(message), move(block_token)); + } + }); + } + + return; + } + if (type == "isInDOMTree"sv) { auto node = message.get_string("node"sv); if (!node.has_value()) { diff --git a/Libraries/LibDevTools/DevToolsDelegate.h b/Libraries/LibDevTools/DevToolsDelegate.h index 7f5250453d9..6c84239d08d 100644 --- a/Libraries/LibDevTools/DevToolsDelegate.h +++ b/Libraries/LibDevTools/DevToolsDelegate.h @@ -51,6 +51,7 @@ public: virtual void add_dom_node_attributes(TabDescription const&, Web::UniqueNodeID, ReadonlySpan, OnDOMNodeEditComplete) const { } virtual void replace_dom_node_attribute(TabDescription const&, Web::UniqueNodeID, String const&, ReadonlySpan, OnDOMNodeEditComplete) const { } virtual void create_child_element(TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const { } + virtual void insert_dom_node_before(TabDescription const&, Web::UniqueNodeID, Web::UniqueNodeID, Optional, OnDOMNodeEditComplete) const { } virtual void clone_dom_node(TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const { } virtual void remove_dom_node(TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const { } diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index 4c4ded2059c..b44472583ce 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -578,6 +578,13 @@ void Application::create_child_element(DevTools::TabDescription const& descripti }); } +void Application::insert_dom_node_before(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id, OnDOMNodeEditComplete on_complete) const +{ + edit_dom_node(description, move(on_complete), [&](auto& view) { + view.insert_dom_node_before(node_id, parent_node_id, sibling_node_id); + }); +} + void Application::clone_dom_node(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, OnDOMNodeEditComplete on_complete) const { edit_dom_node(description, move(on_complete), [&](auto& view) { diff --git a/Libraries/LibWebView/Application.h b/Libraries/LibWebView/Application.h index 38a1dc52c1a..089aa77ecd2 100644 --- a/Libraries/LibWebView/Application.h +++ b/Libraries/LibWebView/Application.h @@ -108,6 +108,7 @@ private: virtual void add_dom_node_attributes(DevTools::TabDescription const&, Web::UniqueNodeID, ReadonlySpan, OnDOMNodeEditComplete) const override; virtual void replace_dom_node_attribute(DevTools::TabDescription const&, Web::UniqueNodeID, String const&, ReadonlySpan, OnDOMNodeEditComplete) const override; virtual void create_child_element(DevTools::TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const override; + virtual void insert_dom_node_before(DevTools::TabDescription const&, Web::UniqueNodeID, Web::UniqueNodeID, Optional, OnDOMNodeEditComplete) const override; virtual void clone_dom_node(DevTools::TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const override; virtual void remove_dom_node(DevTools::TabDescription const&, Web::UniqueNodeID, OnDOMNodeEditComplete) const override; virtual void evaluate_javascript(DevTools::TabDescription const&, String const&, OnScriptEvaluationComplete) const override; diff --git a/Libraries/LibWebView/ViewImplementation.cpp b/Libraries/LibWebView/ViewImplementation.cpp index 913a8ec6476..3f6eb244da0 100644 --- a/Libraries/LibWebView/ViewImplementation.cpp +++ b/Libraries/LibWebView/ViewImplementation.cpp @@ -399,6 +399,11 @@ void ViewImplementation::create_child_text_node(Web::UniqueNodeID node_id) client().async_create_child_text_node(page_id(), node_id); } +void ViewImplementation::insert_dom_node_before(Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id) +{ + client().async_insert_dom_node_before(page_id(), node_id, parent_node_id, sibling_node_id); +} + void ViewImplementation::clone_dom_node(Web::UniqueNodeID node_id) { client().async_clone_dom_node(page_id(), node_id); diff --git a/Libraries/LibWebView/ViewImplementation.h b/Libraries/LibWebView/ViewImplementation.h index 8631e709e2d..f7bda02a300 100644 --- a/Libraries/LibWebView/ViewImplementation.h +++ b/Libraries/LibWebView/ViewImplementation.h @@ -124,6 +124,7 @@ public: void replace_dom_node_attribute(Web::UniqueNodeID node_id, String const& name, ReadonlySpan replacement_attributes); void create_child_element(Web::UniqueNodeID node_id); void create_child_text_node(Web::UniqueNodeID node_id); + void insert_dom_node_before(Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id); void clone_dom_node(Web::UniqueNodeID node_id); void remove_dom_node(Web::UniqueNodeID node_id); diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index 96beded38f8..7be9cae59c3 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -849,6 +849,30 @@ void ConnectionFromClient::create_child_text_node(u64 page_id, Web::UniqueNodeID async_did_finish_editing_dom_node(page_id, text_node->unique_id()); } +void ConnectionFromClient::insert_dom_node_before(u64 page_id, Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id) +{ + auto* dom_node = Web::DOM::Node::from_unique_id(node_id); + auto* parent_dom_node = Web::DOM::Node::from_unique_id(parent_node_id); + + if (!dom_node || !parent_dom_node) { + async_did_finish_editing_dom_node(page_id, {}); + return; + } + + GC::Ptr sibling_dom_node; + if (sibling_node_id.has_value()) { + sibling_dom_node = Web::DOM::Node::from_unique_id(*sibling_node_id); + + if (!sibling_dom_node) { + async_did_finish_editing_dom_node(page_id, {}); + return; + } + } + + parent_dom_node->insert_before(*dom_node, sibling_dom_node); + async_did_finish_editing_dom_node(page_id, dom_node->unique_id()); +} + void ConnectionFromClient::clone_dom_node(u64 page_id, Web::UniqueNodeID node_id) { auto* dom_node = Web::DOM::Node::from_unique_id(node_id); diff --git a/Services/WebContent/ConnectionFromClient.h b/Services/WebContent/ConnectionFromClient.h index 8831734a772..9fa9b7c8f14 100644 --- a/Services/WebContent/ConnectionFromClient.h +++ b/Services/WebContent/ConnectionFromClient.h @@ -93,6 +93,7 @@ private: virtual void replace_dom_node_attribute(u64 page_id, Web::UniqueNodeID node_id, String name, Vector replacement_attributes) override; virtual void create_child_element(u64 page_id, Web::UniqueNodeID node_id) override; virtual void create_child_text_node(u64 page_id, Web::UniqueNodeID node_id) override; + virtual void insert_dom_node_before(u64 page_id, Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id) override; virtual void clone_dom_node(u64 page_id, Web::UniqueNodeID node_id) override; virtual void remove_dom_node(u64 page_id, Web::UniqueNodeID node_id) override; diff --git a/Services/WebContent/WebContentServer.ipc b/Services/WebContent/WebContentServer.ipc index 1cac3cb8b33..16d8ffd7d45 100644 --- a/Services/WebContent/WebContentServer.ipc +++ b/Services/WebContent/WebContentServer.ipc @@ -66,6 +66,7 @@ endpoint WebContentServer replace_dom_node_attribute(u64 page_id, Web::UniqueNodeID node_id, String name, Vector replacement_attributes) =| create_child_element(u64 page_id, Web::UniqueNodeID node_id) =| create_child_text_node(u64 page_id, Web::UniqueNodeID node_id) =| + insert_dom_node_before(u64 page_id, Web::UniqueNodeID node_id, Web::UniqueNodeID parent_node_id, Optional sibling_node_id) =| clone_dom_node(u64 page_id, Web::UniqueNodeID node_id) =| remove_dom_node(u64 page_id, Web::UniqueNodeID node_id) =|