mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-11 02:29:21 +00:00
Inspector: Add a basic style sheet inspector
Choosing options from the `<select>` will load and display that style sheet's source text, with some checks to make sure that the text that just loaded is the one we currently want. The UI is a little goofy when scrolling, as it uses `position: sticky` which we don't implement yet. But that's just more motivation to implement it! :^)
This commit is contained in:
parent
49b2eb5f51
commit
da171c3230
Notes:
github-actions[bot]
2024-09-03 09:12:56 +00:00
Author: https://github.com/AtkinsSJ
Commit: da171c3230
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1168
Reviewed-by: https://github.com/trflynn89
18 changed files with 270 additions and 2 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
:root {
|
||||||
|
--code-font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--background: rgb(23, 23, 23);
|
--background: rgb(23, 23, 23);
|
||||||
|
@ -174,6 +178,17 @@ body {
|
||||||
overflow: auto scroll;
|
overflow: auto scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 2px; /* FIXME: Remove this when https://github.com/LadybirdBrowser/ladybird/issues/1245 is resolved. */
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: var(--tab-controls);
|
||||||
|
border-top: 2px solid var(--background);
|
||||||
|
display: flex;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
details > :not(:first-child) {
|
details > :not(:first-child) {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
list-style: none inside;
|
list-style: none inside;
|
||||||
|
@ -204,7 +219,7 @@ details > :not(:first-child) {
|
||||||
}
|
}
|
||||||
|
|
||||||
.console {
|
.console {
|
||||||
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
font-family: var(--code-font-family);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -330,3 +345,14 @@ details > :not(:first-child) {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#style-sheet-picker {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#style-sheet-source {
|
||||||
|
font-size: 10pt;
|
||||||
|
font-family: var(--code-font-family);
|
||||||
|
white-space: pre;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
|
@ -199,6 +199,97 @@ inspector.addAttributeToDOMNodeID = nodeID => {
|
||||||
pendingEditDOMNode = null;
|
pendingEditDOMNode = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inspector.setStyleSheets = styleSheets => {
|
||||||
|
const styleSheetPicker = document.getElementById("style-sheet-picker");
|
||||||
|
const styleSheetSource = document.getElementById("style-sheet-source");
|
||||||
|
styleSheetPicker.replaceChildren();
|
||||||
|
styleSheetSource.innerHTML = "";
|
||||||
|
|
||||||
|
function addOption(styleSheet, text) {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.innerText = text;
|
||||||
|
if (styleSheet.type) {
|
||||||
|
option.dataset["type"] = styleSheet.type;
|
||||||
|
}
|
||||||
|
if (styleSheet.domNodeId) {
|
||||||
|
option.dataset["domNodeId"] = styleSheet.domNodeId;
|
||||||
|
}
|
||||||
|
if (styleSheet.url) {
|
||||||
|
option.dataset["url"] = styleSheet.url;
|
||||||
|
}
|
||||||
|
styleSheetPicker.add(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (styleSheets.length > 0) {
|
||||||
|
let styleElementIndex = 1;
|
||||||
|
for (const styleSheet of styleSheets) {
|
||||||
|
switch (styleSheet.type) {
|
||||||
|
case "StyleElement":
|
||||||
|
addOption(styleSheet, `Style element #${styleElementIndex++}`);
|
||||||
|
break;
|
||||||
|
case "LinkElement":
|
||||||
|
addOption(styleSheet, styleSheet.url);
|
||||||
|
break;
|
||||||
|
case "ImportRule":
|
||||||
|
addOption(styleSheet, styleSheet.url);
|
||||||
|
break;
|
||||||
|
case "UserAgent":
|
||||||
|
addOption(styleSheet, `User agent: ${styleSheet.url}`);
|
||||||
|
break;
|
||||||
|
case "UserStyle":
|
||||||
|
addOption(styleSheet, "User style");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
styleSheetPicker.disabled = false;
|
||||||
|
} else {
|
||||||
|
addOption({}, "No style sheets found");
|
||||||
|
styleSheetPicker.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
styleSheetPicker.selectedIndex = 0;
|
||||||
|
|
||||||
|
if (!styleSheetPicker.disabled) {
|
||||||
|
loadStyleSheet();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadStyleSheet = () => {
|
||||||
|
const styleSheetPicker = document.getElementById("style-sheet-picker");
|
||||||
|
const styleSheetSource = document.getElementById("style-sheet-source");
|
||||||
|
const selectedOption = styleSheetPicker.selectedOptions[0];
|
||||||
|
|
||||||
|
styleSheetSource.innerHTML = "Loading...";
|
||||||
|
inspector.requestStyleSheetSource(
|
||||||
|
selectedOption.dataset["type"],
|
||||||
|
selectedOption.dataset["domNodeId"],
|
||||||
|
selectedOption.dataset["url"]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
inspector.setStyleSheetSource = (identifier, sourceBase64) => {
|
||||||
|
const styleSheetPicker = document.getElementById("style-sheet-picker");
|
||||||
|
const styleSheetSource = document.getElementById("style-sheet-source");
|
||||||
|
const selectedOption = styleSheetPicker.selectedOptions[0];
|
||||||
|
|
||||||
|
// Make sure this is the source for the currently-selected style sheet.
|
||||||
|
// NOTE: These are != not !== intentionally.
|
||||||
|
if (
|
||||||
|
identifier.type != selectedOption.dataset["type"] ||
|
||||||
|
identifier.domNodeId != selectedOption.dataset["domNodeId"] ||
|
||||||
|
identifier.url != selectedOption.dataset["url"]
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(identifier),
|
||||||
|
"doesn't match",
|
||||||
|
JSON.stringify(selectedOption.dataset)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
styleSheetSource.innerHTML = decodeBase64(sourceBase64);
|
||||||
|
};
|
||||||
|
|
||||||
inspector.createPropertyTables = (computedStyle, resolvedStyle, customProperties) => {
|
inspector.createPropertyTables = (computedStyle, resolvedStyle, customProperties) => {
|
||||||
const createPropertyTable = (tableID, properties) => {
|
const createPropertyTable = (tableID, properties) => {
|
||||||
let oldTable = document.getElementById(tableID);
|
let oldTable = document.getElementById(tableID);
|
||||||
|
|
|
@ -326,6 +326,10 @@ Tab::Tab(BrowserWindow* window, RefPtr<WebView::WebContentClient> parent_client,
|
||||||
m_window->new_tab_from_content(html, Web::HTML::ActivateTab::Yes);
|
m_window->new_tab_from_content(html, Web::HTML::ActivateTab::Yes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
view().on_inspector_requested_style_sheet_source = [this](auto const& identifier) {
|
||||||
|
view().request_style_sheet_source(identifier);
|
||||||
|
};
|
||||||
|
|
||||||
view().on_navigate_back = [this]() {
|
view().on_navigate_back = [this]() {
|
||||||
back();
|
back();
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <LibWeb/Bindings/InspectorPrototype.h>
|
#include <LibWeb/Bindings/InspectorPrototype.h>
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/CSS/Selector.h>
|
#include <LibWeb/CSS/Selector.h>
|
||||||
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/DOM/NamedNodeMap.h>
|
#include <LibWeb/DOM/NamedNodeMap.h>
|
||||||
#include <LibWeb/HTML/BrowsingContext.h>
|
#include <LibWeb/HTML/BrowsingContext.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
|
@ -76,6 +77,18 @@ void Inspector::request_dom_tree_context_menu(i32 node_id, i32 client_x, i32 cli
|
||||||
inspector_page_client().inspector_did_request_dom_tree_context_menu(node_id, { client_x, client_y }, type, tag, attribute_index.map([](auto index) { return static_cast<size_t>(index); }));
|
inspector_page_client().inspector_did_request_dom_tree_context_menu(node_id, { client_x, client_y }, type, tag, attribute_index.map([](auto index) { return static_cast<size_t>(index); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inspector::request_style_sheet_source(String const& type_string, Optional<i32> const& dom_node_unique_id, Optional<String> const& url)
|
||||||
|
{
|
||||||
|
auto type = CSS::style_sheet_identifier_type_from_string(type_string);
|
||||||
|
VERIFY(type.has_value());
|
||||||
|
|
||||||
|
inspector_page_client().inspector_did_request_style_sheet_source({
|
||||||
|
.type = type.value(),
|
||||||
|
.dom_element_unique_id = dom_node_unique_id,
|
||||||
|
.url = url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Inspector::execute_console_script(String const& script)
|
void Inspector::execute_console_script(String const& script)
|
||||||
{
|
{
|
||||||
inspector_page_client().inspector_did_execute_console_script(script);
|
inspector_page_client().inspector_did_execute_console_script(script);
|
||||||
|
|
|
@ -29,6 +29,8 @@ public:
|
||||||
|
|
||||||
void request_dom_tree_context_menu(i32 node_id, i32 client_x, i32 client_y, String const& type, Optional<String> const& tag, Optional<WebIDL::UnsignedLongLong> const& attribute_index);
|
void request_dom_tree_context_menu(i32 node_id, i32 client_x, i32 client_y, String const& type, Optional<String> const& tag, Optional<WebIDL::UnsignedLongLong> const& attribute_index);
|
||||||
|
|
||||||
|
void request_style_sheet_source(String const& type, Optional<i32> const& dom_node_unique_id, Optional<String> const& url);
|
||||||
|
|
||||||
void execute_console_script(String const& script);
|
void execute_console_script(String const& script);
|
||||||
|
|
||||||
void export_inspector_html(String const& html);
|
void export_inspector_html(String const& html);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
undefined requestDOMTreeContextMenu(long nodeID, long clientX, long clientY, DOMString type, DOMString? tag, unsigned long long? attributeIndex);
|
undefined requestDOMTreeContextMenu(long nodeID, long clientX, long clientY, DOMString type, DOMString? tag, unsigned long long? attributeIndex);
|
||||||
|
|
||||||
|
undefined requestStyleSheetSource(DOMString type, long? domNodeID, DOMString? url);
|
||||||
|
|
||||||
undefined executeConsoleScript(DOMString script);
|
undefined executeConsoleScript(DOMString script);
|
||||||
|
|
||||||
undefined exportInspectorHTML(DOMString html);
|
undefined exportInspectorHTML(DOMString html);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <LibWeb/CSS/PreferredContrast.h>
|
#include <LibWeb/CSS/PreferredContrast.h>
|
||||||
#include <LibWeb/CSS/PreferredMotion.h>
|
#include <LibWeb/CSS/PreferredMotion.h>
|
||||||
#include <LibWeb/CSS/Selector.h>
|
#include <LibWeb/CSS/Selector.h>
|
||||||
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/Cookie/Cookie.h>
|
#include <LibWeb/Cookie/Cookie.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
#include <LibWeb/HTML/ActivateTab.h>
|
#include <LibWeb/HTML/ActivateTab.h>
|
||||||
|
@ -376,6 +377,7 @@ public:
|
||||||
virtual void inspector_did_add_dom_node_attributes([[maybe_unused]] i32 node_id, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> attributes) { }
|
virtual void inspector_did_add_dom_node_attributes([[maybe_unused]] i32 node_id, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> attributes) { }
|
||||||
virtual void inspector_did_replace_dom_node_attribute([[maybe_unused]] i32 node_id, [[maybe_unused]] size_t attribute_index, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> replacement_attributes) { }
|
virtual void inspector_did_replace_dom_node_attribute([[maybe_unused]] i32 node_id, [[maybe_unused]] size_t attribute_index, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> replacement_attributes) { }
|
||||||
virtual void inspector_did_request_dom_tree_context_menu([[maybe_unused]] i32 node_id, [[maybe_unused]] CSSPixelPoint position, [[maybe_unused]] String const& type, [[maybe_unused]] Optional<String> const& tag, [[maybe_unused]] Optional<size_t> const& attribute_index) { }
|
virtual void inspector_did_request_dom_tree_context_menu([[maybe_unused]] i32 node_id, [[maybe_unused]] CSSPixelPoint position, [[maybe_unused]] String const& type, [[maybe_unused]] Optional<String> const& tag, [[maybe_unused]] Optional<size_t> const& attribute_index) { }
|
||||||
|
virtual void inspector_did_request_style_sheet_source([[maybe_unused]] CSS::StyleSheetIdentifier const& identifier) { }
|
||||||
virtual void inspector_did_execute_console_script([[maybe_unused]] String const& script) { }
|
virtual void inspector_did_execute_console_script([[maybe_unused]] String const& script) { }
|
||||||
virtual void inspector_did_export_inspector_html([[maybe_unused]] String const& html) { }
|
virtual void inspector_did_export_inspector_html([[maybe_unused]] String const& html) { }
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,14 @@ static ErrorOr<JsonValue> parse_json_tree(StringView json)
|
||||||
return parsed_tree;
|
return parsed_tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String style_sheet_identifier_to_json(Web::CSS::StyleSheetIdentifier const& identifier)
|
||||||
|
{
|
||||||
|
return MUST(String::formatted("{{ type: '{}', domNodeId: {}, url: '{}' }}"sv,
|
||||||
|
Web::CSS::style_sheet_identifier_type_to_string(identifier.type),
|
||||||
|
identifier.dom_element_unique_id.map([](auto& it) { return MUST(String::number(it)); }).value_or("undefined"_string),
|
||||||
|
identifier.url.value_or("undefined"_string)));
|
||||||
|
}
|
||||||
|
|
||||||
InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImplementation& inspector_web_view)
|
InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImplementation& inspector_web_view)
|
||||||
: m_content_web_view(content_web_view)
|
: m_content_web_view(content_web_view)
|
||||||
, m_inspector_web_view(inspector_web_view)
|
, m_inspector_web_view(inspector_web_view)
|
||||||
|
@ -105,6 +113,26 @@ InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImple
|
||||||
select_node(node_id);
|
select_node(node_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_content_web_view.on_received_style_sheet_list = [this](auto const& style_sheets) {
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append("inspector.setStyleSheets(["sv);
|
||||||
|
for (auto& style_sheet : style_sheets) {
|
||||||
|
builder.appendff("{}, "sv, style_sheet_identifier_to_json(style_sheet));
|
||||||
|
}
|
||||||
|
builder.append("]);"sv);
|
||||||
|
|
||||||
|
m_inspector_web_view.run_javascript(builder.string_view());
|
||||||
|
};
|
||||||
|
|
||||||
|
m_content_web_view.on_received_style_sheet_source = [this](Web::CSS::StyleSheetIdentifier const& identifier, String const& source) {
|
||||||
|
// TODO: Highlight it
|
||||||
|
auto escaped_source = escape_html_entities(source.bytes()).replace("\t"sv, " "sv, ReplaceMode::All);
|
||||||
|
auto script = MUST(String::formatted("inspector.setStyleSheetSource({}, \"{}\");",
|
||||||
|
style_sheet_identifier_to_json(identifier),
|
||||||
|
MUST(encode_base64(escaped_source.bytes()))));
|
||||||
|
m_inspector_web_view.run_javascript(script);
|
||||||
|
};
|
||||||
|
|
||||||
m_content_web_view.on_finshed_editing_dom_node = [this](auto const& node_id) {
|
m_content_web_view.on_finshed_editing_dom_node = [this](auto const& node_id) {
|
||||||
m_pending_selection = node_id;
|
m_pending_selection = node_id;
|
||||||
m_dom_tree_loaded = false;
|
m_dom_tree_loaded = false;
|
||||||
|
@ -181,6 +209,10 @@ InspectorClient::InspectorClient(ViewImplementation& content_web_view, ViewImple
|
||||||
m_content_web_view.replace_dom_node_attribute(node_id, attribute.name, replacement_attributes);
|
m_content_web_view.replace_dom_node_attribute(node_id, attribute.name, replacement_attributes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_inspector_web_view.on_inspector_requested_style_sheet_source = [this](auto const& identifier) {
|
||||||
|
m_content_web_view.request_style_sheet_source(identifier);
|
||||||
|
};
|
||||||
|
|
||||||
m_inspector_web_view.on_inspector_executed_console_script = [this](auto const& script) {
|
m_inspector_web_view.on_inspector_executed_console_script = [this](auto const& script) {
|
||||||
append_console_source(script);
|
append_console_source(script);
|
||||||
|
|
||||||
|
@ -241,6 +273,8 @@ InspectorClient::~InspectorClient()
|
||||||
m_content_web_view.on_received_dom_node_properties = nullptr;
|
m_content_web_view.on_received_dom_node_properties = nullptr;
|
||||||
m_content_web_view.on_received_dom_tree = nullptr;
|
m_content_web_view.on_received_dom_tree = nullptr;
|
||||||
m_content_web_view.on_received_hovered_node_id = nullptr;
|
m_content_web_view.on_received_hovered_node_id = nullptr;
|
||||||
|
m_content_web_view.on_received_style_sheet_list = nullptr;
|
||||||
|
m_content_web_view.on_inspector_requested_style_sheet_source = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorClient::inspect()
|
void InspectorClient::inspect()
|
||||||
|
@ -250,6 +284,7 @@ void InspectorClient::inspect()
|
||||||
|
|
||||||
m_content_web_view.inspect_dom_tree();
|
m_content_web_view.inspect_dom_tree();
|
||||||
m_content_web_view.inspect_accessibility_tree();
|
m_content_web_view.inspect_accessibility_tree();
|
||||||
|
m_content_web_view.list_style_sheets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorClient::reset()
|
void InspectorClient::reset()
|
||||||
|
@ -420,6 +455,7 @@ void InspectorClient::load_inspector()
|
||||||
<div class="tab-controls">
|
<div class="tab-controls">
|
||||||
<button id="dom-tree-button" onclick="selectTopTab(this, 'dom-tree')">DOM Tree</button>
|
<button id="dom-tree-button" onclick="selectTopTab(this, 'dom-tree')">DOM Tree</button>
|
||||||
<button id="accessibility-tree-button" onclick="selectTopTab(this, 'accessibility-tree')">Accessibility Tree</button>
|
<button id="accessibility-tree-button" onclick="selectTopTab(this, 'accessibility-tree')">Accessibility Tree</button>
|
||||||
|
<button id="style-sheets-button" onclick="selectTopTab(this, 'style-sheets')">Style Sheets</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="global-controls">
|
<div class="global-controls">
|
||||||
<button id="export-inspector-button" title="Export the Inspector to an HTML file" onclick="inspector.exportInspector()"></button>
|
<button id="export-inspector-button" title="Export the Inspector to an HTML file" onclick="inspector.exportInspector()"></button>
|
||||||
|
@ -427,6 +463,14 @@ void InspectorClient::load_inspector()
|
||||||
</div>
|
</div>
|
||||||
<div id="dom-tree" class="tab-content html"></div>
|
<div id="dom-tree" class="tab-content html"></div>
|
||||||
<div id="accessibility-tree" class="tab-content"></div>
|
<div id="accessibility-tree" class="tab-content"></div>
|
||||||
|
<div id="style-sheets" class="tab-content" style="padding: 0">
|
||||||
|
<div class="tab-header">
|
||||||
|
<select id="style-sheet-picker" disabled onchange="loadStyleSheet()">
|
||||||
|
<option value="." selected>No style sheets found</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div id="style-sheet-source"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="inspector-separator" class="split-view-separator">
|
<div id="inspector-separator" class="split-view-separator">
|
||||||
<svg viewBox="0 0 16 5" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 16 5" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|
|
@ -305,6 +305,16 @@ void ViewImplementation::get_dom_node_html(i32 node_id)
|
||||||
client().async_get_dom_node_html(page_id(), node_id);
|
client().async_get_dom_node_html(page_id(), node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewImplementation::list_style_sheets()
|
||||||
|
{
|
||||||
|
client().async_list_style_sheets(page_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewImplementation::request_style_sheet_source(Web::CSS::StyleSheetIdentifier const& identifier)
|
||||||
|
{
|
||||||
|
client().async_request_style_sheet_source(page_id(), identifier);
|
||||||
|
}
|
||||||
|
|
||||||
void ViewImplementation::debug_request(ByteString const& request, ByteString const& argument)
|
void ViewImplementation::debug_request(ByteString const& request, ByteString const& argument)
|
||||||
{
|
{
|
||||||
client().async_debug_request(page_id(), request, argument);
|
client().async_debug_request(page_id(), request, argument);
|
||||||
|
|
|
@ -97,6 +97,9 @@ public:
|
||||||
void remove_dom_node(i32 node_id);
|
void remove_dom_node(i32 node_id);
|
||||||
void get_dom_node_html(i32 node_id);
|
void get_dom_node_html(i32 node_id);
|
||||||
|
|
||||||
|
void list_style_sheets();
|
||||||
|
void request_style_sheet_source(Web::CSS::StyleSheetIdentifier const&);
|
||||||
|
|
||||||
void debug_request(ByteString const& request, ByteString const& argument = {});
|
void debug_request(ByteString const& request, ByteString const& argument = {});
|
||||||
|
|
||||||
void run_javascript(StringView);
|
void run_javascript(StringView);
|
||||||
|
@ -182,6 +185,9 @@ public:
|
||||||
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(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(Vector<Web::CSS::StyleSheetIdentifier>)> on_received_style_sheet_list;
|
||||||
|
Function<void(Web::CSS::StyleSheetIdentifier const&)> on_inspector_requested_style_sheet_source;
|
||||||
|
Function<void(Web::CSS::StyleSheetIdentifier const&, String const&)> on_received_style_sheet_source;
|
||||||
Function<void(i32 node_id)> on_received_hovered_node_id;
|
Function<void(i32 node_id)> on_received_hovered_node_id;
|
||||||
Function<void(Optional<i32> const& node_id)> on_finshed_editing_dom_node;
|
Function<void(Optional<i32> const& node_id)> on_finshed_editing_dom_node;
|
||||||
Function<void(String const&)> on_received_dom_node_html;
|
Function<void(String const&)> on_received_dom_node_html;
|
||||||
|
|
|
@ -711,6 +711,30 @@ Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request
|
||||||
return IPC::File {};
|
return IPC::File {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContentClient::inspector_did_list_style_sheets(u64 page_id, Vector<Web::CSS::StyleSheetIdentifier> const& stylesheets)
|
||||||
|
{
|
||||||
|
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||||
|
if (view->on_received_style_sheet_list)
|
||||||
|
view->on_received_style_sheet_list(stylesheets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContentClient::inspector_did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier)
|
||||||
|
{
|
||||||
|
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||||
|
if (view->on_inspector_requested_style_sheet_source)
|
||||||
|
view->on_inspector_requested_style_sheet_source(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContentClient::did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier, String const& source)
|
||||||
|
{
|
||||||
|
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||||
|
if (view->on_received_style_sheet_source)
|
||||||
|
view->on_received_style_sheet_source(identifier, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)
|
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)
|
||||||
{
|
{
|
||||||
if (auto view = m_views.get(page_id); view.has_value())
|
if (auto view = m_views.get(page_id); view.has_value())
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/SourceLocation.h>
|
#include <AK/SourceLocation.h>
|
||||||
#include <LibIPC/ConnectionToServer.h>
|
#include <LibIPC/ConnectionToServer.h>
|
||||||
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/HTML/ActivateTab.h>
|
#include <LibWeb/HTML/ActivateTab.h>
|
||||||
#include <LibWeb/HTML/FileFilter.h>
|
#include <LibWeb/HTML/FileFilter.h>
|
||||||
#include <LibWeb/HTML/SelectItem.h>
|
#include <LibWeb/HTML/SelectItem.h>
|
||||||
|
@ -122,6 +123,9 @@ private:
|
||||||
virtual void inspector_did_execute_console_script(u64 page_id, String const& script) override;
|
virtual void inspector_did_execute_console_script(u64 page_id, String const& script) override;
|
||||||
virtual void inspector_did_export_inspector_html(u64 page_id, String const& html) override;
|
virtual void inspector_did_export_inspector_html(u64 page_id, String const& html) override;
|
||||||
virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id) override;
|
virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id) override;
|
||||||
|
virtual void inspector_did_list_style_sheets(u64 page_id, Vector<Web::CSS::StyleSheetIdentifier> const& stylesheets) override;
|
||||||
|
virtual void inspector_did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier) override;
|
||||||
|
virtual void did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier, String const& source) override;
|
||||||
|
|
||||||
Optional<ViewImplementation&> view_for_page_id(u64, SourceLocation = SourceLocation::current());
|
Optional<ViewImplementation&> view_for_page_id(u64, SourceLocation = SourceLocation::current());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org>
|
||||||
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
|
||||||
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||||
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
|
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
|
||||||
|
@ -629,6 +629,28 @@ void ConnectionFromClient::get_hovered_node_id(u64 page_id)
|
||||||
async_did_get_hovered_node_id(page_id, node_id);
|
async_did_get_hovered_node_id(page_id, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionFromClient::list_style_sheets(u64 page_id)
|
||||||
|
{
|
||||||
|
auto page = this->page(page_id);
|
||||||
|
if (!page.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
|
async_inspector_did_list_style_sheets(page_id, page->list_style_sheets());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionFromClient::request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier)
|
||||||
|
{
|
||||||
|
auto page = this->page(page_id);
|
||||||
|
if (!page.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (auto* document = page->page().top_level_browsing_context().active_document()) {
|
||||||
|
auto stylesheet = document->get_style_sheet_source(identifier);
|
||||||
|
if (stylesheet.has_value())
|
||||||
|
async_did_request_style_sheet_source(page_id, identifier, stylesheet.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConnectionFromClient::set_dom_node_text(u64 page_id, i32 node_id, String const& text)
|
void ConnectionFromClient::set_dom_node_text(u64 page_id, i32 node_id, String const& text)
|
||||||
{
|
{
|
||||||
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
|
||||||
|
|
|
@ -76,6 +76,9 @@ private:
|
||||||
virtual void inspect_accessibility_tree(u64 page_id) override;
|
virtual void inspect_accessibility_tree(u64 page_id) override;
|
||||||
virtual void get_hovered_node_id(u64 page_id) override;
|
virtual void get_hovered_node_id(u64 page_id) override;
|
||||||
|
|
||||||
|
virtual void list_style_sheets(u64 page_id) override;
|
||||||
|
virtual void request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier const& identifier) override;
|
||||||
|
|
||||||
virtual void set_dom_node_text(u64 page_id, i32 node_id, String const& text) override;
|
virtual void set_dom_node_text(u64 page_id, i32 node_id, String const& text) override;
|
||||||
virtual void set_dom_node_tag(u64 page_id, i32 node_id, String const& name) override;
|
virtual void set_dom_node_tag(u64 page_id, i32 node_id, String const& name) override;
|
||||||
virtual void add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> const& attributes) override;
|
virtual void add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> const& attributes) override;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org>
|
||||||
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -657,6 +658,11 @@ void PageClient::inspector_did_request_dom_tree_context_menu(i32 node_id, Web::C
|
||||||
client().async_inspector_did_request_dom_tree_context_menu(m_id, node_id, page().css_to_device_point(position).to_type<int>(), type, tag, attribute_index);
|
client().async_inspector_did_request_dom_tree_context_menu(m_id, node_id, page().css_to_device_point(position).to_type<int>(), type, tag, attribute_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PageClient::inspector_did_request_style_sheet_source(Web::CSS::StyleSheetIdentifier const& identifier)
|
||||||
|
{
|
||||||
|
client().async_inspector_did_request_style_sheet_source(m_id, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
void PageClient::inspector_did_execute_console_script(String const& script)
|
void PageClient::inspector_did_execute_console_script(String const& script)
|
||||||
{
|
{
|
||||||
client().async_inspector_did_execute_console_script(m_id, script);
|
client().async_inspector_did_execute_console_script(m_id, script);
|
||||||
|
|
|
@ -169,6 +169,7 @@ private:
|
||||||
virtual void inspector_did_add_dom_node_attributes(i32 node_id, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> attributes) override;
|
virtual void inspector_did_add_dom_node_attributes(i32 node_id, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> attributes) override;
|
||||||
virtual void inspector_did_replace_dom_node_attribute(i32 node_id, size_t attribute_index, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> replacement_attributes) override;
|
virtual void inspector_did_replace_dom_node_attribute(i32 node_id, size_t attribute_index, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> replacement_attributes) override;
|
||||||
virtual void inspector_did_request_dom_tree_context_menu(i32 node_id, Web::CSSPixelPoint position, String const& type, Optional<String> const& tag, Optional<size_t> const& attribute_index) override;
|
virtual void inspector_did_request_dom_tree_context_menu(i32 node_id, Web::CSSPixelPoint position, String const& type, Optional<String> const& tag, Optional<size_t> const& attribute_index) override;
|
||||||
|
virtual void inspector_did_request_style_sheet_source(Web::CSS::StyleSheetIdentifier const& stylesheet_source) override;
|
||||||
virtual void inspector_did_execute_console_script(String const& script) override;
|
virtual void inspector_did_execute_console_script(String const& script) override;
|
||||||
virtual void inspector_did_export_inspector_html(String const& script) override;
|
virtual void inspector_did_export_inspector_html(String const& script) override;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <LibWeb/Cookie/Cookie.h>
|
#include <LibWeb/Cookie/Cookie.h>
|
||||||
#include <LibWeb/Cookie/ParsedCookie.h>
|
#include <LibWeb/Cookie/ParsedCookie.h>
|
||||||
#include <LibWeb/CSS/Selector.h>
|
#include <LibWeb/CSS/Selector.h>
|
||||||
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/HTML/ActivateTab.h>
|
#include <LibWeb/HTML/ActivateTab.h>
|
||||||
#include <LibWeb/HTML/AudioPlayState.h>
|
#include <LibWeb/HTML/AudioPlayState.h>
|
||||||
#include <LibWeb/HTML/FileFilter.h>
|
#include <LibWeb/HTML/FileFilter.h>
|
||||||
|
@ -54,6 +55,10 @@ endpoint WebContentClient
|
||||||
did_finish_editing_dom_node(u64 page_id, Optional<i32> node_id) =|
|
did_finish_editing_dom_node(u64 page_id, Optional<i32> node_id) =|
|
||||||
did_get_dom_node_html(u64 page_id, String html) =|
|
did_get_dom_node_html(u64 page_id, String html) =|
|
||||||
|
|
||||||
|
inspector_did_list_style_sheets(u64 page_id, Vector<Web::CSS::StyleSheetIdentifier> style_sheets) =|
|
||||||
|
inspector_did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier identifier) =|
|
||||||
|
did_request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier identifier, String source) =|
|
||||||
|
|
||||||
did_take_screenshot(u64 page_id, Gfx::ShareableBitmap screenshot) =|
|
did_take_screenshot(u64 page_id, Gfx::ShareableBitmap screenshot) =|
|
||||||
|
|
||||||
did_change_favicon(u64 page_id, Gfx::ShareableBitmap favicon) =|
|
did_change_favicon(u64 page_id, Gfx::ShareableBitmap favicon) =|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <LibWeb/CSS/PreferredContrast.h>
|
#include <LibWeb/CSS/PreferredContrast.h>
|
||||||
#include <LibWeb/CSS/PreferredMotion.h>
|
#include <LibWeb/CSS/PreferredMotion.h>
|
||||||
#include <LibWeb/CSS/Selector.h>
|
#include <LibWeb/CSS/Selector.h>
|
||||||
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/HTML/ColorPickerUpdateState.h>
|
#include <LibWeb/HTML/ColorPickerUpdateState.h>
|
||||||
#include <LibWeb/HTML/SelectedFile.h>
|
#include <LibWeb/HTML/SelectedFile.h>
|
||||||
#include <LibWeb/Page/InputEvent.h>
|
#include <LibWeb/Page/InputEvent.h>
|
||||||
|
@ -45,6 +46,8 @@ endpoint WebContentServer
|
||||||
get_hovered_node_id(u64 page_id) =|
|
get_hovered_node_id(u64 page_id) =|
|
||||||
js_console_input(u64 page_id, ByteString js_source) =|
|
js_console_input(u64 page_id, ByteString js_source) =|
|
||||||
js_console_request_messages(u64 page_id, i32 start_index) =|
|
js_console_request_messages(u64 page_id, i32 start_index) =|
|
||||||
|
list_style_sheets(u64 page_id) =|
|
||||||
|
request_style_sheet_source(u64 page_id, Web::CSS::StyleSheetIdentifier identifier) =|
|
||||||
|
|
||||||
set_dom_node_text(u64 page_id, i32 node_id, String text) =|
|
set_dom_node_text(u64 page_id, i32 node_id, String text) =|
|
||||||
set_dom_node_tag(u64 page_id, i32 node_id, String name) =|
|
set_dom_node_tag(u64 page_id, i32 node_id, String name) =|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue