mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibDevTools+LibWebView+WebContent: Implement editing DOM node HTML
These commands are used for the "Edit As HTML" feature in DevTools. This renames our existing HTML getter IPC to indicate that it is for outer HTML. DevTools will need a separate inner HTML getter.
This commit is contained in:
parent
aca4385daf
commit
d75eadc3c4
Notes:
github-actions[bot]
2025-03-11 13:52:05 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/d75eadc3c45 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3898
11 changed files with 155 additions and 32 deletions
|
@ -214,6 +214,36 @@ void WalkerActor::handle_message(StringView type, JsonObject const& message)
|
|||
return;
|
||||
}
|
||||
|
||||
if (type == "outerHTML"sv) {
|
||||
auto node = message.get_string("node"sv);
|
||||
if (!node.has_value()) {
|
||||
send_missing_parameter_error("node"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto dom_node = WalkerActor::dom_node_for(*this, *node); dom_node.has_value()) {
|
||||
auto block_token = block_responses();
|
||||
|
||||
devtools().delegate().get_dom_node_outer_html(
|
||||
dom_node->tab->description(), dom_node->identifier.id,
|
||||
[weak_self = make_weak_ptr<WalkerActor>(), block_token = move(block_token)](ErrorOr<String> html) mutable {
|
||||
if (html.is_error()) {
|
||||
dbgln_if(DEVTOOLS_DEBUG, "Unable to edit DOM node: {}", html.error());
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto self = weak_self.strong_ref()) {
|
||||
JsonObject message;
|
||||
message.set("from"sv, self->name());
|
||||
message.set("value"sv, html.release_value());
|
||||
self->send_message(move(message), move(block_token));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == "previousSibling"sv) {
|
||||
auto node = message.get_string("node"sv);
|
||||
if (!node.has_value()) {
|
||||
|
@ -307,6 +337,41 @@ void WalkerActor::handle_message(StringView type, JsonObject const& message)
|
|||
return;
|
||||
}
|
||||
|
||||
if (type == "setOuterHTML"sv) {
|
||||
auto node = message.get_string("node"sv);
|
||||
if (!node.has_value()) {
|
||||
send_missing_parameter_error("node"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
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(*this, *node); dom_node.has_value()) {
|
||||
auto block_token = block_responses();
|
||||
|
||||
devtools().delegate().set_dom_node_outer_html(
|
||||
dom_node->tab->description(), dom_node->identifier.id, value.release_value(),
|
||||
[weak_self = make_weak_ptr<WalkerActor>(), block_token = move(block_token)](ErrorOr<Web::UniqueNodeID> 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 == "watchRootNode"sv) {
|
||||
response.set("type"sv, "root-available"sv);
|
||||
response.set("node"sv, serialize_root());
|
||||
|
|
|
@ -41,7 +41,10 @@ public:
|
|||
virtual void listen_for_dom_mutations(TabDescription const&, OnDOMMutationReceived) const { }
|
||||
virtual void stop_listening_for_dom_mutations(TabDescription const&) const { }
|
||||
|
||||
using OnDOMNodeHTMLReceived = Function<void(ErrorOr<String>)>;
|
||||
using OnDOMNodeEditComplete = Function<void(ErrorOr<Web::UniqueNodeID>)>;
|
||||
virtual void get_dom_node_outer_html(TabDescription const&, Web::UniqueNodeID, OnDOMNodeHTMLReceived) const { }
|
||||
virtual void set_dom_node_outer_html(TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const { }
|
||||
virtual void set_dom_node_text(TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const { }
|
||||
virtual void set_dom_node_tag(TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const { }
|
||||
virtual void add_dom_node_attributes(TabDescription const&, Web::UniqueNodeID, ReadonlySpan<WebView::Attribute>, OnDOMNodeEditComplete) const { }
|
||||
|
|
|
@ -504,6 +504,29 @@ static void edit_dom_node(DevTools::TabDescription const& description, Applicati
|
|||
edit(*view);
|
||||
}
|
||||
|
||||
void Application::get_dom_node_outer_html(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, OnDOMNodeHTMLReceived on_complete) const
|
||||
{
|
||||
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_received_dom_node_html = [&view = *view, on_complete = move(on_complete)](auto html) {
|
||||
view.on_received_dom_node_html = nullptr;
|
||||
on_complete(html);
|
||||
};
|
||||
|
||||
view->get_dom_node_outer_html(node_id);
|
||||
}
|
||||
|
||||
void Application::set_dom_node_outer_html(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, String const& value, OnDOMNodeEditComplete on_complete) const
|
||||
{
|
||||
edit_dom_node(description, move(on_complete), [&](auto& view) {
|
||||
view.set_dom_node_outer_html(node_id, value);
|
||||
});
|
||||
}
|
||||
|
||||
void Application::set_dom_node_text(DevTools::TabDescription const& description, Web::UniqueNodeID node_id, String const& value, OnDOMNodeEditComplete on_complete) const
|
||||
{
|
||||
edit_dom_node(description, move(on_complete), [&](auto& view) {
|
||||
|
|
|
@ -100,6 +100,8 @@ 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 get_dom_node_outer_html(DevTools::TabDescription const&, Web::UniqueNodeID, OnDOMNodeHTMLReceived) const override;
|
||||
virtual void set_dom_node_outer_html(DevTools::TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const override;
|
||||
virtual void set_dom_node_text(DevTools::TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const override;
|
||||
virtual void set_dom_node_tag(DevTools::TabDescription const&, Web::UniqueNodeID, String const&, OnDOMNodeEditComplete) const override;
|
||||
virtual void add_dom_node_attributes(DevTools::TabDescription const&, Web::UniqueNodeID, ReadonlySpan<Attribute>, OnDOMNodeEditComplete) const override;
|
||||
|
|
|
@ -368,7 +368,7 @@ void InspectorClient::context_menu_copy_dom_node()
|
|||
{
|
||||
VERIFY(m_context_menu_data.has_value());
|
||||
|
||||
m_content_web_view.get_dom_node_html(m_context_menu_data->dom_node_id);
|
||||
m_content_web_view.get_dom_node_outer_html(m_context_menu_data->dom_node_id);
|
||||
m_context_menu_data.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -354,6 +354,16 @@ void ViewImplementation::set_listen_for_dom_mutations(bool listen_for_dom_mutati
|
|||
client().async_set_listen_for_dom_mutations(page_id(), listen_for_dom_mutations);
|
||||
}
|
||||
|
||||
void ViewImplementation::get_dom_node_outer_html(Web::UniqueNodeID node_id)
|
||||
{
|
||||
client().async_get_dom_node_outer_html(page_id(), node_id);
|
||||
}
|
||||
|
||||
void ViewImplementation::set_dom_node_outer_html(Web::UniqueNodeID node_id, String const& html)
|
||||
{
|
||||
client().async_set_dom_node_outer_html(page_id(), node_id, html);
|
||||
}
|
||||
|
||||
void ViewImplementation::set_dom_node_text(Web::UniqueNodeID node_id, String const& text)
|
||||
{
|
||||
client().async_set_dom_node_text(page_id(), node_id, text);
|
||||
|
@ -394,11 +404,6 @@ void ViewImplementation::remove_dom_node(Web::UniqueNodeID node_id)
|
|||
client().async_remove_dom_node(page_id(), node_id);
|
||||
}
|
||||
|
||||
void ViewImplementation::get_dom_node_html(Web::UniqueNodeID node_id)
|
||||
{
|
||||
client().async_get_dom_node_html(page_id(), node_id);
|
||||
}
|
||||
|
||||
void ViewImplementation::list_style_sheets()
|
||||
{
|
||||
client().async_list_style_sheets(page_id());
|
||||
|
|
|
@ -115,6 +115,8 @@ public:
|
|||
void clear_highlighted_dom_node();
|
||||
|
||||
void set_listen_for_dom_mutations(bool);
|
||||
void get_dom_node_outer_html(Web::UniqueNodeID node_id);
|
||||
void set_dom_node_outer_html(Web::UniqueNodeID node_id, String const& html);
|
||||
void set_dom_node_text(Web::UniqueNodeID node_id, String const& text);
|
||||
void set_dom_node_tag(Web::UniqueNodeID node_id, String const& name);
|
||||
void add_dom_node_attributes(Web::UniqueNodeID node_id, ReadonlySpan<Attribute> attributes);
|
||||
|
@ -123,7 +125,6 @@ public:
|
|||
void create_child_text_node(Web::UniqueNodeID node_id);
|
||||
void clone_dom_node(Web::UniqueNodeID node_id);
|
||||
void remove_dom_node(Web::UniqueNodeID node_id);
|
||||
void get_dom_node_html(Web::UniqueNodeID node_id);
|
||||
|
||||
void list_style_sheets();
|
||||
void request_style_sheet_source(Web::CSS::StyleSheetIdentifier const&);
|
||||
|
@ -218,7 +219,7 @@ public:
|
|||
Function<void(Web::UniqueNodeID)> on_received_hovered_node_id;
|
||||
Function<void(Mutation)> on_dom_mutation_received;
|
||||
Function<void(Optional<Web::UniqueNodeID> const& node_id)> on_finshed_editing_dom_node;
|
||||
Function<void(String const&)> on_received_dom_node_html;
|
||||
Function<void(String)> on_received_dom_node_html;
|
||||
Function<void(JsonValue)> on_received_js_console_result;
|
||||
Function<void(i32 message_id)> on_console_message_available;
|
||||
Function<void(i32 start_index, Vector<String> const& message_types, Vector<String> const& messages)> on_received_styled_console_messages;
|
||||
|
|
|
@ -371,7 +371,7 @@ void WebContentClient::did_get_dom_node_html(u64 page_id, String html)
|
|||
{
|
||||
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||
if (view->on_received_dom_node_html)
|
||||
view->on_received_dom_node_html(html);
|
||||
view->on_received_dom_node_html(move(html));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -676,6 +676,49 @@ void ConnectionFromClient::set_listen_for_dom_mutations(u64 page_id, bool listen
|
|||
page->page().set_listen_for_dom_mutations(listen_for_dom_mutations);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::get_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id)
|
||||
{
|
||||
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
||||
if (!dom_node)
|
||||
return;
|
||||
|
||||
String html;
|
||||
|
||||
if (dom_node->is_element()) {
|
||||
auto const& element = static_cast<Web::DOM::Element const&>(*dom_node);
|
||||
html = element.outer_html().release_value_but_fixme_should_propagate_errors();
|
||||
} else if (dom_node->is_text() || dom_node->is_comment()) {
|
||||
auto const& character_data = static_cast<Web::DOM::CharacterData const&>(*dom_node);
|
||||
html = character_data.data();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
async_did_get_dom_node_html(page_id, html);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::set_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id, String html)
|
||||
{
|
||||
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
||||
if (!dom_node) {
|
||||
async_did_finish_editing_dom_node(page_id, {});
|
||||
return;
|
||||
}
|
||||
|
||||
if (dom_node->is_element()) {
|
||||
auto& element = static_cast<Web::DOM::Element&>(*dom_node);
|
||||
element.set_outer_html(html).release_value_but_fixme_should_propagate_errors();
|
||||
} else if (dom_node->is_text() || dom_node->is_comment()) {
|
||||
auto& character_data = static_cast<Web::DOM::CharacterData&>(*dom_node);
|
||||
character_data.set_data(html);
|
||||
} else {
|
||||
async_did_finish_editing_dom_node(page_id, {});
|
||||
return;
|
||||
}
|
||||
|
||||
async_did_finish_editing_dom_node(page_id, node_id);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::set_dom_node_text(u64 page_id, Web::UniqueNodeID node_id, String text)
|
||||
{
|
||||
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
||||
|
@ -826,27 +869,6 @@ void ConnectionFromClient::remove_dom_node(u64 page_id, Web::UniqueNodeID node_i
|
|||
async_did_finish_editing_dom_node(page_id, previous_dom_node->unique_id());
|
||||
}
|
||||
|
||||
void ConnectionFromClient::get_dom_node_html(u64 page_id, Web::UniqueNodeID node_id)
|
||||
{
|
||||
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
||||
if (!dom_node)
|
||||
return;
|
||||
|
||||
String html;
|
||||
|
||||
if (dom_node->is_element()) {
|
||||
auto const& element = static_cast<Web::DOM::Element const&>(*dom_node);
|
||||
html = element.outer_html().release_value_but_fixme_should_propagate_errors();
|
||||
} else if (dom_node->is_text() || dom_node->is_comment()) {
|
||||
auto const& character_data = static_cast<Web::DOM::CharacterData const&>(*dom_node);
|
||||
html = character_data.data();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
async_did_get_dom_node_html(page_id, html);
|
||||
}
|
||||
|
||||
void ConnectionFromClient::take_document_screenshot(u64 page_id)
|
||||
{
|
||||
auto page = this->page(page_id);
|
||||
|
|
|
@ -84,6 +84,8 @@ private:
|
|||
virtual void request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier identifier) override;
|
||||
|
||||
virtual void set_listen_for_dom_mutations(u64 page_id, bool) override;
|
||||
virtual void get_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id) override;
|
||||
virtual void set_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id, String html) override;
|
||||
virtual void set_dom_node_text(u64 page_id, Web::UniqueNodeID node_id, String text) override;
|
||||
virtual void set_dom_node_tag(u64 page_id, Web::UniqueNodeID node_id, String name) override;
|
||||
virtual void add_dom_node_attributes(u64 page_id, Web::UniqueNodeID node_id, Vector<WebView::Attribute> attributes) override;
|
||||
|
@ -92,7 +94,6 @@ private:
|
|||
virtual void create_child_text_node(u64 page_id, Web::UniqueNodeID 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;
|
||||
virtual void get_dom_node_html(u64 page_id, Web::UniqueNodeID node_id) override;
|
||||
|
||||
virtual void set_content_filters(u64 page_id, Vector<String>) override;
|
||||
virtual void set_autoplay_allowed_on_all_websites(u64 page_id) override;
|
||||
|
|
|
@ -57,6 +57,8 @@ endpoint WebContentServer
|
|||
request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier identifier) =|
|
||||
|
||||
set_listen_for_dom_mutations(u64 page_id, bool listen_for_dom_mutations) =|
|
||||
get_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
set_dom_node_outer_html(u64 page_id, Web::UniqueNodeID node_id, String html) =|
|
||||
set_dom_node_text(u64 page_id, Web::UniqueNodeID node_id, String text) =|
|
||||
set_dom_node_tag(u64 page_id, Web::UniqueNodeID node_id, String name) =|
|
||||
add_dom_node_attributes(u64 page_id, Web::UniqueNodeID node_id, Vector<WebView::Attribute> attributes) =|
|
||||
|
@ -65,7 +67,6 @@ endpoint WebContentServer
|
|||
create_child_text_node(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
clone_dom_node(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
remove_dom_node(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
get_dom_node_html(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
|
||||
take_document_screenshot(u64 page_id) =|
|
||||
take_dom_node_screenshot(u64 page_id, Web::UniqueNodeID node_id) =|
|
||||
|
|
Loading…
Add table
Reference in a new issue