Skip to content

Commit afb0728

Browse files
EpigeneticAtkinsSJ
authored andcommitted
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.
1 parent e9840bf commit afb0728

13 files changed

+179
-17
lines changed

Userland/Applications/Browser/InspectorWidget.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <LibWeb/DOM/Document.h>
1717
#include <LibWeb/DOM/Element.h>
1818
#include <LibWebView/AccessibilityTreeModel.h>
19+
#include <LibWebView/AriaPropertiesStateModel.h>
1920
#include <LibWebView/DOMTreeModel.h>
2021
#include <LibWebView/OutOfProcessWebView.h>
2122
#include <LibWebView/StylePropertiesModel.h>
@@ -67,6 +68,7 @@ void InspectorWidget::set_selection(GUI::ModelIndex const index)
6768
auto inspected_node_properties = maybe_inspected_node_properties.release_value();
6869
load_style_json(inspected_node_properties.computed_style_json, inspected_node_properties.resolved_style_json, inspected_node_properties.custom_properties_json);
6970
update_node_box_model(inspected_node_properties.node_box_sizing_json);
71+
update_aria_properties_state_model(inspected_node_properties.aria_properties_state_json);
7072
} else {
7173
clear_style_json();
7274
clear_node_box_model();
@@ -117,6 +119,10 @@ InspectorWidget::InspectorWidget()
117119
m_element_size_view = box_model_widget.add<ElementSizePreviewWidget>();
118120
m_element_size_view->set_should_hide_unnecessary_scrollbars(true);
119121

122+
auto& aria_properties_state_widget = bottom_tab_widget.add_tab<GUI::Widget>("ARIA"_string.release_value_but_fixme_should_propagate_errors());
123+
aria_properties_state_widget.set_layout<GUI::VerticalBoxLayout>(4);
124+
m_aria_properties_state_view = aria_properties_state_widget.add<GUI::TableView>();
125+
120126
m_dom_tree_view->set_focus(true);
121127
}
122128

@@ -146,7 +152,7 @@ void InspectorWidget::clear_dom_json()
146152
m_dom_loaded = false;
147153
}
148154

149-
void InspectorWidget::set_dom_node_properties_json(Selection selection, StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json, StringView node_box_sizing_json)
155+
void InspectorWidget::set_dom_node_properties_json(Selection selection, StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json, StringView node_box_sizing_json, StringView aria_properties_state_json)
150156
{
151157
if (selection != m_selection) {
152158
dbgln("Got data for the wrong node id! Wanted ({}), got ({})", m_selection.to_string(), selection.to_string());
@@ -155,6 +161,7 @@ void InspectorWidget::set_dom_node_properties_json(Selection selection, StringVi
155161

156162
load_style_json(computed_values_json, resolved_values_json, custom_properties_json);
157163
update_node_box_model(node_box_sizing_json);
164+
update_aria_properties_state_model(aria_properties_state_json);
158165
}
159166

160167
void InspectorWidget::load_style_json(StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json)
@@ -196,6 +203,12 @@ void InspectorWidget::update_node_box_model(StringView node_box_sizing_json)
196203
m_element_size_view->set_box_model(m_node_box_sizing);
197204
}
198205

206+
void InspectorWidget::update_aria_properties_state_model(StringView aria_properties_state_json)
207+
{
208+
m_aria_properties_state_view->set_model(WebView::AriaPropertiesStateModel::create(aria_properties_state_json).release_value_but_fixme_should_propagate_errors());
209+
m_aria_properties_state_view->set_searchable(true);
210+
}
211+
199212
void InspectorWidget::clear_node_box_model()
200213
{
201214
m_node_box_sizing = Web::Layout::BoxModelMetrics {};
@@ -209,6 +222,7 @@ void InspectorWidget::clear_style_json()
209222
m_computed_style_table_view->set_model(nullptr);
210223
m_resolved_style_table_view->set_model(nullptr);
211224
m_custom_properties_table_view->set_model(nullptr);
225+
m_aria_properties_state_view->set_model(nullptr);
212226

213227
m_element_size_view->set_box_model({});
214228
m_element_size_view->set_node_content_width(0);

Userland/Applications/Browser/InspectorWidget.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class InspectorWidget final : public GUI::Widget {
4444
void set_web_view(NonnullRefPtr<WebView::OutOfProcessWebView> web_view) { m_web_view = web_view; }
4545
void set_dom_json(StringView);
4646
void clear_dom_json();
47-
void set_dom_node_properties_json(Selection, StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json, StringView node_box_sizing_json);
47+
void set_dom_node_properties_json(Selection, StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json, StringView node_box_sizing_json, StringView aria_properties_state_json);
4848
void set_accessibility_json(StringView);
4949

5050
void set_selection(Selection);
@@ -56,6 +56,7 @@ class InspectorWidget final : public GUI::Widget {
5656
void set_selection(GUI::ModelIndex);
5757
void load_style_json(StringView computed_values_json, StringView resolved_values_json, StringView custom_properties_json);
5858
void update_node_box_model(StringView node_box_sizing_json);
59+
void update_aria_properties_state_model(StringView aria_properties_state_json);
5960
void clear_style_json();
6061
void clear_node_box_model();
6162

@@ -66,6 +67,7 @@ class InspectorWidget final : public GUI::Widget {
6667
RefPtr<GUI::TableView> m_computed_style_table_view;
6768
RefPtr<GUI::TableView> m_resolved_style_table_view;
6869
RefPtr<GUI::TableView> m_custom_properties_table_view;
70+
RefPtr<GUI::TableView> m_aria_properties_state_view;
6971
RefPtr<ElementSizePreviewWidget> m_element_size_view;
7072

7173
Web::Layout::BoxModelMetrics m_node_box_sizing;

Userland/Applications/Browser/Tab.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,8 @@ Tab::Tab(BrowserWindow& window)
519519
m_dom_inspector_widget->set_dom_json(dom_tree);
520520
};
521521

522-
view().on_get_dom_node_properties = [this](auto node_id, auto& specified, auto& computed, auto& custom_properties, auto& node_box_sizing) {
523-
m_dom_inspector_widget->set_dom_node_properties_json({ node_id }, specified, computed, custom_properties, node_box_sizing);
522+
view().on_get_dom_node_properties = [this](auto node_id, auto& specified, auto& computed, auto& custom_properties, auto& node_box_sizing, auto& aria_properties_state) {
523+
m_dom_inspector_widget->set_dom_node_properties_json({ node_id }, specified, computed, custom_properties, node_box_sizing, aria_properties_state);
524524
};
525525

526526
view().on_get_accessibility_tree = [this](auto& accessibility_tree) {
@@ -821,7 +821,7 @@ void Tab::show_inspector_window(Browser::Tab::InspectorTarget inspector_target)
821821
if (!m_dom_inspector_widget) {
822822
auto window = GUI::Window::construct(&this->window());
823823
window->set_window_mode(GUI::WindowMode::Modeless);
824-
window->resize(300, 500);
824+
window->resize(325, 500);
825825
window->set_title("Inspector");
826826
window->set_icon(g_icon_bag.inspector_object);
827827
window->on_close = [&]() {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include "AriaPropertiesStateModel.h"
8+
9+
namespace WebView {
10+
11+
AriaPropertiesStateModel::AriaPropertiesStateModel(JsonObject properties_state)
12+
: m_properties_state(move(properties_state))
13+
{
14+
m_properties_state.for_each_member([&](auto property_name, JsonValue const& values) {
15+
Value value;
16+
value.name = property_name;
17+
value.value = "";
18+
m_values.append(value);
19+
values.as_object().for_each_member([&](auto property_name, auto& property_value) {
20+
Value value;
21+
value.name = property_name;
22+
value.value = property_value.to_deprecated_string();
23+
m_values.append(value);
24+
});
25+
});
26+
}
27+
28+
AriaPropertiesStateModel::~AriaPropertiesStateModel() = default;
29+
30+
int AriaPropertiesStateModel::row_count(GUI::ModelIndex const&) const
31+
{
32+
return m_values.size();
33+
}
34+
35+
ErrorOr<String> AriaPropertiesStateModel::column_name(int column_index) const
36+
{
37+
switch (column_index) {
38+
case Column::PropertyName:
39+
return "Name"_short_string;
40+
case Column::PropertyValue:
41+
return "Value"_short_string;
42+
default:
43+
return Error::from_string_view("Unexpected column index"sv);
44+
}
45+
}
46+
47+
GUI::Variant AriaPropertiesStateModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const
48+
{
49+
auto& value = m_values[index.row()];
50+
if (role == GUI::ModelRole::Display) {
51+
if (index.column() == Column::PropertyName)
52+
return value.name;
53+
if (index.column() == Column::PropertyValue)
54+
return value.value;
55+
}
56+
57+
return {};
58+
}
59+
60+
Vector<GUI::ModelIndex> AriaPropertiesStateModel::matches(AK::StringView searching, unsigned int flags, GUI::ModelIndex const& parent)
61+
{
62+
if (m_values.is_empty())
63+
return {};
64+
Vector<GUI::ModelIndex> found_indices;
65+
for (auto it = m_values.begin(); !it.is_end(); ++it) {
66+
GUI::ModelIndex index = this->index(it.index(), Column::PropertyName, parent);
67+
if (!string_matches(data(index, GUI::ModelRole::Display).as_string(), searching, flags))
68+
continue;
69+
70+
found_indices.append(index);
71+
if (flags & FirstMatchOnly)
72+
break;
73+
}
74+
return found_indices;
75+
}
76+
77+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <AK/JsonObject.h>
10+
#include <LibGUI/Model.h>
11+
12+
namespace WebView {
13+
14+
class AriaPropertiesStateModel final : public GUI::Model {
15+
public:
16+
enum Column {
17+
PropertyName,
18+
PropertyValue,
19+
__Count
20+
};
21+
22+
static ErrorOr<NonnullRefPtr<AriaPropertiesStateModel>> create(StringView properties_state)
23+
{
24+
auto json_or_error = TRY(JsonValue::from_string(properties_state));
25+
return adopt_nonnull_ref_or_enomem(new AriaPropertiesStateModel(json_or_error.as_object()));
26+
}
27+
28+
virtual ~AriaPropertiesStateModel() override;
29+
30+
virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override;
31+
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
32+
virtual ErrorOr<String> column_name(int) const override;
33+
virtual GUI::Variant data(GUI::ModelIndex const&, GUI::ModelRole) const override;
34+
virtual bool is_searchable() const override { return true; }
35+
virtual Vector<GUI::ModelIndex> matches(StringView, unsigned flags, GUI::ModelIndex const&) override;
36+
37+
private:
38+
explicit AriaPropertiesStateModel(JsonObject);
39+
40+
JsonObject m_properties_state;
41+
42+
struct Value {
43+
DeprecatedString name;
44+
DeprecatedString value;
45+
};
46+
Vector<Value> m_values;
47+
};
48+
49+
}

Userland/Libraries/LibWebView/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set(SOURCES
22
AccessibilityTreeModel.cpp
3+
AriaPropertiesStateModel.cpp
34
DOMTreeModel.cpp
45
OutOfProcessWebView.cpp
56
RequestServerAdapter.cpp

Userland/Libraries/LibWebView/ViewImplementation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ ErrorOr<ViewImplementation::DOMNodeProperties> ViewImplementation::inspect_dom_n
118118
.resolved_style_json = TRY(String::from_deprecated_string(response.take_resolved_style())),
119119
.custom_properties_json = TRY(String::from_deprecated_string(response.take_custom_properties())),
120120
.node_box_sizing_json = TRY(String::from_deprecated_string(response.take_node_box_sizing())),
121+
.aria_properties_state_json = TRY(String::from_deprecated_string(response.take_aria_properties_state())),
121122
};
122123
}
123124

Userland/Libraries/LibWebView/ViewImplementation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ViewImplementation {
4444
String resolved_style_json;
4545
String custom_properties_json;
4646
String node_box_sizing_json;
47+
String aria_properties_state_json;
4748
};
4849

4950
void set_url(Badge<WebContentClient>, AK::URL url) { m_url = move(url); }
@@ -110,7 +111,7 @@ class ViewImplementation {
110111
Function<void(Gfx::Bitmap const&)> on_favicon_change;
111112
Function<void(const AK::URL&, DeprecatedString const&)> on_get_source;
112113
Function<void(DeprecatedString const&)> on_get_dom_tree;
113-
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;
114+
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;
114115
Function<void(DeprecatedString const&)> on_get_accessibility_tree;
115116
Function<void(i32 message_id)> on_js_console_new_message;
116117
Function<void(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages)> on_get_js_console_messages;

Userland/Libraries/LibWebView/WebContentClient.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ void WebContentClient::did_get_dom_tree(DeprecatedString const& dom_tree)
194194
m_view.on_get_dom_tree(dom_tree);
195195
}
196196

197-
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)
197+
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)
198198
{
199199
if (m_view.on_get_dom_node_properties)
200-
m_view.on_get_dom_node_properties(node_id, computed_style, resolved_style, custom_properties, node_box_sizing);
200+
m_view.on_get_dom_node_properties(node_id, computed_style, resolved_style, custom_properties, node_box_sizing, aria_properties_state);
201201
}
202202

203203
void WebContentClient::did_get_accessibility_tree(DeprecatedString const& accessibility_tree)

Userland/Libraries/LibWebView/WebContentClient.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class WebContentClient final
5555
virtual void did_request_media_context_menu(Gfx::IntPoint, DeprecatedString const&, unsigned, Web::Page::MediaContextMenu const&) override;
5656
virtual void did_get_source(AK::URL const&, DeprecatedString const&) override;
5757
virtual void did_get_dom_tree(DeprecatedString const&) override;
58-
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;
58+
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;
5959
virtual void did_get_accessibility_tree(DeprecatedString const&) override;
6060
virtual void did_output_js_console_message(i32 message_index) override;
6161
virtual void did_get_js_console_messages(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages) override;

0 commit comments

Comments
 (0)