mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWebView+WebContent: Make the DOM node inspection IPC async
This commit is contained in:
parent
4c3bff264e
commit
760ba5932b
Notes:
sideshowbarker
2024-07-18 00:41:35 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/760ba5932b Pull-request: https://github.com/SerenityOS/serenity/pull/22504
9 changed files with 80 additions and 53 deletions
|
@ -49,6 +49,32 @@ InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImple
|
||||||
select_default_node();
|
select_default_node();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_content_web_view.on_received_dom_node_properties = [this](auto const& inspected_node_properties) {
|
||||||
|
StringBuilder builder;
|
||||||
|
|
||||||
|
// FIXME: Support box model metrics and ARIA properties.
|
||||||
|
auto generate_property_script = [&](auto const& computed_style, auto const& resolved_style, auto const& custom_properties) {
|
||||||
|
builder.append("inspector.createPropertyTables(\""sv);
|
||||||
|
builder.append_escaped_for_json(computed_style);
|
||||||
|
builder.append("\", \""sv);
|
||||||
|
builder.append_escaped_for_json(resolved_style);
|
||||||
|
builder.append("\", \""sv);
|
||||||
|
builder.append_escaped_for_json(custom_properties);
|
||||||
|
builder.append("\");"sv);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (inspected_node_properties.has_value()) {
|
||||||
|
generate_property_script(
|
||||||
|
inspected_node_properties->computed_style_json,
|
||||||
|
inspected_node_properties->resolved_style_json,
|
||||||
|
inspected_node_properties->custom_properties_json);
|
||||||
|
} else {
|
||||||
|
generate_property_script("{}"sv, "{}"sv, "{}"sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_inspector_web_view.run_javascript(builder.string_view());
|
||||||
|
};
|
||||||
|
|
||||||
m_content_web_view.on_received_accessibility_tree = [this](auto const& accessibility_tree) {
|
m_content_web_view.on_received_accessibility_tree = [this](auto const& accessibility_tree) {
|
||||||
auto result = parse_json_tree(accessibility_tree);
|
auto result = parse_json_tree(accessibility_tree);
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
|
@ -101,31 +127,7 @@ InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImple
|
||||||
};
|
};
|
||||||
|
|
||||||
m_inspector_web_view.on_inspector_selected_dom_node = [this](auto node_id, auto const& pseudo_element) {
|
m_inspector_web_view.on_inspector_selected_dom_node = [this](auto node_id, auto const& pseudo_element) {
|
||||||
auto inspected_node_properties = m_content_web_view.inspect_dom_node(node_id, pseudo_element);
|
m_content_web_view.inspect_dom_node(node_id, pseudo_element);
|
||||||
|
|
||||||
StringBuilder builder;
|
|
||||||
|
|
||||||
// FIXME: Support box model metrics and ARIA properties.
|
|
||||||
auto generate_property_script = [&](auto const& computed_style, auto const& resolved_style, auto const& custom_properties) {
|
|
||||||
builder.append("inspector.createPropertyTables(\""sv);
|
|
||||||
builder.append_escaped_for_json(computed_style);
|
|
||||||
builder.append("\", \""sv);
|
|
||||||
builder.append_escaped_for_json(resolved_style);
|
|
||||||
builder.append("\", \""sv);
|
|
||||||
builder.append_escaped_for_json(custom_properties);
|
|
||||||
builder.append("\");"sv);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (inspected_node_properties.is_error()) {
|
|
||||||
generate_property_script("{}"sv, "{}"sv, "{}"sv);
|
|
||||||
} else {
|
|
||||||
generate_property_script(
|
|
||||||
inspected_node_properties.value().computed_style_json,
|
|
||||||
inspected_node_properties.value().resolved_style_json,
|
|
||||||
inspected_node_properties.value().custom_properties_json);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_inspector_web_view.run_javascript(builder.string_view());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
m_inspector_web_view.on_inspector_set_dom_node_text = [this](auto node_id, auto const& text) {
|
m_inspector_web_view.on_inspector_set_dom_node_text = [this](auto node_id, auto const& text) {
|
||||||
|
|
|
@ -131,28 +131,19 @@ void ViewImplementation::inspect_dom_tree()
|
||||||
client().async_inspect_dom_tree();
|
client().async_inspect_dom_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewImplementation::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element)
|
||||||
|
{
|
||||||
|
client().async_inspect_dom_node(node_id, move(pseudo_element));
|
||||||
|
}
|
||||||
|
|
||||||
void ViewImplementation::inspect_accessibility_tree()
|
void ViewImplementation::inspect_accessibility_tree()
|
||||||
{
|
{
|
||||||
client().async_inspect_accessibility_tree();
|
client().async_inspect_accessibility_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<ViewImplementation::DOMNodeProperties> ViewImplementation::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element)
|
|
||||||
{
|
|
||||||
auto response = client().inspect_dom_node(node_id, pseudo_element);
|
|
||||||
if (!response.has_style())
|
|
||||||
return Error::from_string_view("Inspected node returned no style"sv);
|
|
||||||
return DOMNodeProperties {
|
|
||||||
.computed_style_json = TRY(String::from_byte_string(response.take_computed_style())),
|
|
||||||
.resolved_style_json = TRY(String::from_byte_string(response.take_resolved_style())),
|
|
||||||
.custom_properties_json = TRY(String::from_byte_string(response.take_custom_properties())),
|
|
||||||
.node_box_sizing_json = TRY(String::from_byte_string(response.take_node_box_sizing())),
|
|
||||||
.aria_properties_state_json = TRY(String::from_byte_string(response.take_aria_properties_state())),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewImplementation::clear_inspected_dom_node()
|
void ViewImplementation::clear_inspected_dom_node()
|
||||||
{
|
{
|
||||||
client().inspect_dom_node(0, {});
|
inspect_dom_node(0, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 ViewImplementation::get_hovered_node_id()
|
i32 ViewImplementation::get_hovered_node_id()
|
||||||
|
|
|
@ -59,8 +59,8 @@ public:
|
||||||
void get_source();
|
void get_source();
|
||||||
|
|
||||||
void inspect_dom_tree();
|
void inspect_dom_tree();
|
||||||
|
void inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element);
|
||||||
void inspect_accessibility_tree();
|
void inspect_accessibility_tree();
|
||||||
ErrorOr<DOMNodeProperties> inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element);
|
|
||||||
void clear_inspected_dom_node();
|
void clear_inspected_dom_node();
|
||||||
i32 get_hovered_node_id();
|
i32 get_hovered_node_id();
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ public:
|
||||||
Function<void()> on_request_dismiss_dialog;
|
Function<void()> on_request_dismiss_dialog;
|
||||||
Function<void(const AK::URL&, ByteString const&)> on_received_source;
|
Function<void(const AK::URL&, ByteString const&)> on_received_source;
|
||||||
Function<void(ByteString const&)> on_received_dom_tree;
|
Function<void(ByteString const&)> on_received_dom_tree;
|
||||||
|
Function<void(Optional<DOMNodeProperties>)> on_received_dom_node_properties;
|
||||||
Function<void(ByteString const&)> on_received_accessibility_tree;
|
Function<void(ByteString const&)> on_received_accessibility_tree;
|
||||||
Function<void(i32 message_id)> on_received_console_message;
|
Function<void(i32 message_id)> on_received_console_message;
|
||||||
Function<void(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)> on_received_console_messages;
|
Function<void(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)> on_received_console_messages;
|
||||||
|
|
|
@ -187,6 +187,26 @@ void WebContentClient::did_inspect_dom_tree(ByteString const& dom_tree)
|
||||||
m_view.on_received_dom_tree(dom_tree);
|
m_view.on_received_dom_tree(dom_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContentClient::did_inspect_dom_node(bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state)
|
||||||
|
{
|
||||||
|
if (!m_view.on_received_dom_node_properties)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Optional<ViewImplementation::DOMNodeProperties> properties;
|
||||||
|
|
||||||
|
if (has_style) {
|
||||||
|
properties = ViewImplementation::DOMNodeProperties {
|
||||||
|
.computed_style_json = MUST(String::from_byte_string(computed_style)),
|
||||||
|
.resolved_style_json = MUST(String::from_byte_string(resolved_style)),
|
||||||
|
.custom_properties_json = MUST(String::from_byte_string(custom_properties)),
|
||||||
|
.node_box_sizing_json = MUST(String::from_byte_string(node_box_sizing)),
|
||||||
|
.aria_properties_state_json = MUST(String::from_byte_string(aria_properties_state)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_view.on_received_dom_node_properties(move(properties));
|
||||||
|
}
|
||||||
|
|
||||||
void WebContentClient::did_inspect_accessibility_tree(ByteString const& accessibility_tree)
|
void WebContentClient::did_inspect_accessibility_tree(ByteString const& accessibility_tree)
|
||||||
{
|
{
|
||||||
if (m_view.on_received_accessibility_tree)
|
if (m_view.on_received_accessibility_tree)
|
||||||
|
|
|
@ -53,6 +53,7 @@ private:
|
||||||
virtual void did_request_media_context_menu(Gfx::IntPoint, ByteString const&, unsigned, Web::Page::MediaContextMenu const&) override;
|
virtual void did_request_media_context_menu(Gfx::IntPoint, ByteString const&, unsigned, Web::Page::MediaContextMenu const&) override;
|
||||||
virtual void did_get_source(AK::URL const&, ByteString const&) override;
|
virtual void did_get_source(AK::URL const&, ByteString const&) override;
|
||||||
virtual void did_inspect_dom_tree(ByteString const&) override;
|
virtual void did_inspect_dom_tree(ByteString const&) override;
|
||||||
|
virtual void did_inspect_dom_node(bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state) override;
|
||||||
virtual void did_inspect_accessibility_tree(ByteString const&) override;
|
virtual void did_inspect_accessibility_tree(ByteString const&) override;
|
||||||
virtual void did_output_js_console_message(i32 message_index) override;
|
virtual void did_output_js_console_message(i32 message_index) override;
|
||||||
virtual void did_get_js_console_messages(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages) override;
|
virtual void did_get_js_console_messages(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages) override;
|
||||||
|
|
|
@ -474,7 +474,7 @@ void ConnectionFromClient::inspect_dom_tree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
|
void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
|
||||||
{
|
{
|
||||||
auto& top_context = page().page().top_level_browsing_context();
|
auto& top_context = page().page().top_level_browsing_context();
|
||||||
|
|
||||||
|
@ -488,15 +488,18 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect
|
||||||
Web::DOM::Node* node = Web::DOM::Node::from_unique_id(node_id);
|
Web::DOM::Node* node = Web::DOM::Node::from_unique_id(node_id);
|
||||||
// Note: Nodes without layout (aka non-visible nodes, don't have style computed)
|
// Note: Nodes without layout (aka non-visible nodes, don't have style computed)
|
||||||
if (!node || !node->layout_node()) {
|
if (!node || !node->layout_node()) {
|
||||||
return { false, "", "", "", "", "" };
|
async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->document().set_inspected_node(node, pseudo_element);
|
node->document().set_inspected_node(node, pseudo_element);
|
||||||
|
|
||||||
if (node->is_element()) {
|
if (node->is_element()) {
|
||||||
auto& element = verify_cast<Web::DOM::Element>(*node);
|
auto& element = verify_cast<Web::DOM::Element>(*node);
|
||||||
if (!element.computed_css_values())
|
if (!element.computed_css_values()) {
|
||||||
return { false, "", "", "", "", "" };
|
async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto serialize_json = [](Web::CSS::StyleProperties const& properties) -> ByteString {
|
auto serialize_json = [](Web::CSS::StyleProperties const& properties) -> ByteString {
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
|
@ -580,8 +583,10 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect
|
||||||
|
|
||||||
if (pseudo_element.has_value()) {
|
if (pseudo_element.has_value()) {
|
||||||
auto pseudo_element_node = element.get_pseudo_element_node(pseudo_element.value());
|
auto pseudo_element_node = element.get_pseudo_element_node(pseudo_element.value());
|
||||||
if (!pseudo_element_node)
|
if (!pseudo_element_node) {
|
||||||
return { false, "", "", "", "", "" };
|
async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Pseudo-elements only exist as Layout::Nodes, which don't have style information
|
// FIXME: Pseudo-elements only exist as Layout::Nodes, which don't have style information
|
||||||
// in a format we can use. So, we run the StyleComputer again to get the specified
|
// in a format we can use. So, we run the StyleComputer again to get the specified
|
||||||
|
@ -591,18 +596,22 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect
|
||||||
ByteString resolved_values = "{}";
|
ByteString resolved_values = "{}";
|
||||||
ByteString custom_properties_json = serialize_custom_properties_json(element, pseudo_element);
|
ByteString custom_properties_json = serialize_custom_properties_json(element, pseudo_element);
|
||||||
ByteString node_box_sizing_json = serialize_node_box_sizing_json(pseudo_element_node.ptr());
|
ByteString node_box_sizing_json = serialize_node_box_sizing_json(pseudo_element_node.ptr());
|
||||||
return { true, computed_values, resolved_values, custom_properties_json, node_box_sizing_json, "" };
|
|
||||||
|
async_did_inspect_dom_node(true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), {});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString computed_values = serialize_json(*element.computed_css_values());
|
ByteString computed_values = serialize_json(*element.computed_css_values());
|
||||||
ByteString resolved_values_json = serialize_json(element.resolved_css_values());
|
ByteString resolved_values = serialize_json(element.resolved_css_values());
|
||||||
ByteString custom_properties_json = serialize_custom_properties_json(element, {});
|
ByteString custom_properties_json = serialize_custom_properties_json(element, {});
|
||||||
ByteString node_box_sizing_json = serialize_node_box_sizing_json(element.layout_node());
|
ByteString node_box_sizing_json = serialize_node_box_sizing_json(element.layout_node());
|
||||||
ByteString aria_properties_state_json = serialize_aria_properties_state_json(element);
|
ByteString aria_properties_state_json = serialize_aria_properties_state_json(element);
|
||||||
return { true, computed_values, resolved_values_json, custom_properties_json, node_box_sizing_json, aria_properties_state_json };
|
|
||||||
|
async_did_inspect_dom_node(true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), move(aria_properties_state_json));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { false, "", "", "", "", "" };
|
async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFromClient::inspect_accessibility_tree()
|
void ConnectionFromClient::inspect_accessibility_tree()
|
||||||
|
|
|
@ -72,7 +72,7 @@ private:
|
||||||
virtual void debug_request(ByteString const&, ByteString const&) override;
|
virtual void debug_request(ByteString const&, ByteString const&) override;
|
||||||
virtual void get_source() override;
|
virtual void get_source() override;
|
||||||
virtual void inspect_dom_tree() override;
|
virtual void inspect_dom_tree() override;
|
||||||
virtual Messages::WebContentServer::InspectDomNodeResponse inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
|
virtual void inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
|
||||||
virtual void inspect_accessibility_tree() override;
|
virtual void inspect_accessibility_tree() override;
|
||||||
virtual Messages::WebContentServer::GetHoveredNodeIdResponse get_hovered_node_id() override;
|
virtual Messages::WebContentServer::GetHoveredNodeIdResponse get_hovered_node_id() override;
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,11 @@ endpoint WebContentClient
|
||||||
did_request_accept_dialog() =|
|
did_request_accept_dialog() =|
|
||||||
did_request_dismiss_dialog() =|
|
did_request_dismiss_dialog() =|
|
||||||
did_get_source(URL url, ByteString source) =|
|
did_get_source(URL url, ByteString source) =|
|
||||||
|
|
||||||
did_inspect_dom_tree(ByteString dom_tree) =|
|
did_inspect_dom_tree(ByteString dom_tree) =|
|
||||||
|
did_inspect_dom_node(bool has_style, ByteString computed_style, ByteString resolved_style, ByteString custom_properties, ByteString node_box_sizing, ByteString aria_properties_state) =|
|
||||||
did_inspect_accessibility_tree(ByteString accessibility_tree) =|
|
did_inspect_accessibility_tree(ByteString accessibility_tree) =|
|
||||||
|
|
||||||
did_change_favicon(Gfx::ShareableBitmap favicon) =|
|
did_change_favicon(Gfx::ShareableBitmap favicon) =|
|
||||||
did_request_all_cookies(URL url) => (Vector<Web::Cookie::Cookie> cookies)
|
did_request_all_cookies(URL url) => (Vector<Web::Cookie::Cookie> cookies)
|
||||||
did_request_named_cookie(URL url, ByteString name) => (Optional<Web::Cookie::Cookie> cookie)
|
did_request_named_cookie(URL url, ByteString name) => (Optional<Web::Cookie::Cookie> cookie)
|
||||||
|
|
|
@ -38,7 +38,7 @@ endpoint WebContentServer
|
||||||
debug_request(ByteString request, ByteString argument) =|
|
debug_request(ByteString request, ByteString argument) =|
|
||||||
get_source() =|
|
get_source() =|
|
||||||
inspect_dom_tree() =|
|
inspect_dom_tree() =|
|
||||||
inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) => (bool has_style, ByteString computed_style, ByteString resolved_style, ByteString custom_properties, ByteString node_box_sizing, ByteString aria_properties_state)
|
inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
|
||||||
inspect_accessibility_tree() =|
|
inspect_accessibility_tree() =|
|
||||||
get_hovered_node_id() => (i32 node_id)
|
get_hovered_node_id() => (i32 node_id)
|
||||||
js_console_input(ByteString js_source) =|
|
js_console_input(ByteString js_source) =|
|
||||||
|
|
Loading…
Reference in a new issue