1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 21:07:34 +00:00

Browser+LibWebView: Load and Display ARIA Properites and State

The inspector widget now has a new ARIA tab which displays an
individual element's ARIA properties and state. The view itself
is pretty basic for now, just being a table- there is definitely room
for some better UX here but it's enough for a first cut.
This commit is contained in:
Jonah 2023-05-21 08:52:03 -05:00 committed by Sam Atkins
parent e9840bfd4e
commit afb07281ad
13 changed files with 179 additions and 17 deletions

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "AriaPropertiesStateModel.h"
namespace WebView {
AriaPropertiesStateModel::AriaPropertiesStateModel(JsonObject properties_state)
: m_properties_state(move(properties_state))
{
m_properties_state.for_each_member([&](auto property_name, JsonValue const& values) {
Value value;
value.name = property_name;
value.value = "";
m_values.append(value);
values.as_object().for_each_member([&](auto property_name, auto& property_value) {
Value value;
value.name = property_name;
value.value = property_value.to_deprecated_string();
m_values.append(value);
});
});
}
AriaPropertiesStateModel::~AriaPropertiesStateModel() = default;
int AriaPropertiesStateModel::row_count(GUI::ModelIndex const&) const
{
return m_values.size();
}
ErrorOr<String> AriaPropertiesStateModel::column_name(int column_index) const
{
switch (column_index) {
case Column::PropertyName:
return "Name"_short_string;
case Column::PropertyValue:
return "Value"_short_string;
default:
return Error::from_string_view("Unexpected column index"sv);
}
}
GUI::Variant AriaPropertiesStateModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const
{
auto& value = m_values[index.row()];
if (role == GUI::ModelRole::Display) {
if (index.column() == Column::PropertyName)
return value.name;
if (index.column() == Column::PropertyValue)
return value.value;
}
return {};
}
Vector<GUI::ModelIndex> AriaPropertiesStateModel::matches(AK::StringView searching, unsigned int flags, GUI::ModelIndex const& parent)
{
if (m_values.is_empty())
return {};
Vector<GUI::ModelIndex> found_indices;
for (auto it = m_values.begin(); !it.is_end(); ++it) {
GUI::ModelIndex index = this->index(it.index(), Column::PropertyName, parent);
if (!string_matches(data(index, GUI::ModelRole::Display).as_string(), searching, flags))
continue;
found_indices.append(index);
if (flags & FirstMatchOnly)
break;
}
return found_indices;
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/JsonObject.h>
#include <LibGUI/Model.h>
namespace WebView {
class AriaPropertiesStateModel final : public GUI::Model {
public:
enum Column {
PropertyName,
PropertyValue,
__Count
};
static ErrorOr<NonnullRefPtr<AriaPropertiesStateModel>> create(StringView properties_state)
{
auto json_or_error = TRY(JsonValue::from_string(properties_state));
return adopt_nonnull_ref_or_enomem(new AriaPropertiesStateModel(json_or_error.as_object()));
}
virtual ~AriaPropertiesStateModel() override;
virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override;
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual ErrorOr<String> column_name(int) const override;
virtual GUI::Variant data(GUI::ModelIndex const&, GUI::ModelRole) const override;
virtual bool is_searchable() const override { return true; }
virtual Vector<GUI::ModelIndex> matches(StringView, unsigned flags, GUI::ModelIndex const&) override;
private:
explicit AriaPropertiesStateModel(JsonObject);
JsonObject m_properties_state;
struct Value {
DeprecatedString name;
DeprecatedString value;
};
Vector<Value> m_values;
};
}

View file

@ -1,5 +1,6 @@
set(SOURCES
AccessibilityTreeModel.cpp
AriaPropertiesStateModel.cpp
DOMTreeModel.cpp
OutOfProcessWebView.cpp
RequestServerAdapter.cpp

View file

@ -118,6 +118,7 @@ ErrorOr<ViewImplementation::DOMNodeProperties> ViewImplementation::inspect_dom_n
.resolved_style_json = TRY(String::from_deprecated_string(response.take_resolved_style())),
.custom_properties_json = TRY(String::from_deprecated_string(response.take_custom_properties())),
.node_box_sizing_json = TRY(String::from_deprecated_string(response.take_node_box_sizing())),
.aria_properties_state_json = TRY(String::from_deprecated_string(response.take_aria_properties_state())),
};
}

View file

@ -44,6 +44,7 @@ public:
String resolved_style_json;
String custom_properties_json;
String node_box_sizing_json;
String aria_properties_state_json;
};
void set_url(Badge<WebContentClient>, AK::URL url) { m_url = move(url); }
@ -110,7 +111,7 @@ public:
Function<void(Gfx::Bitmap const&)> on_favicon_change;
Function<void(const AK::URL&, DeprecatedString const&)> on_get_source;
Function<void(DeprecatedString const&)> on_get_dom_tree;
Function<void(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing)> on_get_dom_node_properties;
Function<void(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing, DeprecatedString const& aria_properties_state)> on_get_dom_node_properties;
Function<void(DeprecatedString const&)> on_get_accessibility_tree;
Function<void(i32 message_id)> on_js_console_new_message;
Function<void(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages)> on_get_js_console_messages;

View file

@ -194,10 +194,10 @@ void WebContentClient::did_get_dom_tree(DeprecatedString const& dom_tree)
m_view.on_get_dom_tree(dom_tree);
}
void WebContentClient::did_get_dom_node_properties(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing)
void WebContentClient::did_get_dom_node_properties(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing, DeprecatedString const& aria_properties_state)
{
if (m_view.on_get_dom_node_properties)
m_view.on_get_dom_node_properties(node_id, computed_style, resolved_style, custom_properties, node_box_sizing);
m_view.on_get_dom_node_properties(node_id, computed_style, resolved_style, custom_properties, node_box_sizing, aria_properties_state);
}
void WebContentClient::did_get_accessibility_tree(DeprecatedString const& accessibility_tree)

View file

@ -55,7 +55,7 @@ private:
virtual void did_request_media_context_menu(Gfx::IntPoint, DeprecatedString const&, unsigned, Web::Page::MediaContextMenu const&) override;
virtual void did_get_source(AK::URL const&, DeprecatedString const&) override;
virtual void did_get_dom_tree(DeprecatedString const&) override;
virtual void did_get_dom_node_properties(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing) override;
virtual void did_get_dom_node_properties(i32 node_id, DeprecatedString const& computed_style, DeprecatedString const& resolved_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing, DeprecatedString const& aria_properties_stae) override;
virtual void did_get_accessibility_tree(DeprecatedString const&) override;
virtual void did_output_js_console_message(i32 message_index) override;
virtual void did_get_js_console_messages(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages) override;