mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-12 14:12:52 +00:00
LibWeb: Add method for listing all style sheets on a page
This will be used by the inspector, for showing style sheet contents. Identifying a specific style sheet is a bit tricky. Depending on where it came from, a style sheet may have a URL, it might be associated with a DOM element, both, or neither. This varied information is wrapped in a new StyleSheetIdentifier struct.
This commit is contained in:
parent
dd3b011f15
commit
51a426cc05
Notes:
github-actions[bot]
2024-09-03 09:13:10 +00:00
Author: https://github.com/AtkinsSJ
Commit: 51a426cc05
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1168
Reviewed-by: https://github.com/trflynn89
10 changed files with 214 additions and 1 deletions
|
@ -102,6 +102,7 @@ set(SOURCES
|
|||
CSS/StyleProperties.cpp
|
||||
CSS/StyleProperty.cpp
|
||||
CSS/StyleSheet.cpp
|
||||
CSS/StyleSheetIdentifier.cpp
|
||||
CSS/StyleSheetList.cpp
|
||||
CSS/StyleValues/AngleStyleValue.cpp
|
||||
CSS/StyleValues/BackgroundRepeatStyleValue.cpp
|
||||
|
|
73
Userland/Libraries/LibWeb/CSS/StyleSheetIdentifier.cpp
Normal file
73
Userland/Libraries/LibWeb/CSS/StyleSheetIdentifier.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "StyleSheetIdentifier.h"
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
StringView style_sheet_identifier_type_to_string(StyleSheetIdentifier::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case StyleSheetIdentifier::Type::StyleElement:
|
||||
return "StyleElement"sv;
|
||||
case StyleSheetIdentifier::Type::LinkElement:
|
||||
return "LinkElement"sv;
|
||||
case StyleSheetIdentifier::Type::ImportRule:
|
||||
return "ImportRule"sv;
|
||||
case StyleSheetIdentifier::Type::UserAgent:
|
||||
return "UserAgent"sv;
|
||||
case StyleSheetIdentifier::Type::UserStyle:
|
||||
return "UserStyle"sv;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
Optional<StyleSheetIdentifier::Type> style_sheet_identifier_type_from_string(StringView string)
|
||||
{
|
||||
if (string == "StyleElement"sv)
|
||||
return StyleSheetIdentifier::Type::StyleElement;
|
||||
if (string == "LinkElement"sv)
|
||||
return StyleSheetIdentifier::Type::LinkElement;
|
||||
if (string == "ImportRule"sv)
|
||||
return StyleSheetIdentifier::Type::ImportRule;
|
||||
if (string == "UserAgent"sv)
|
||||
return StyleSheetIdentifier::Type::UserAgent;
|
||||
if (string == "UserStyle"sv)
|
||||
return StyleSheetIdentifier::Type::UserStyle;
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder& encoder, Web::CSS::StyleSheetIdentifier const& style_sheet_source)
|
||||
{
|
||||
TRY(encoder.encode(style_sheet_source.type));
|
||||
TRY(encoder.encode(style_sheet_source.dom_element_unique_id));
|
||||
TRY(encoder.encode(style_sheet_source.url));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::CSS::StyleSheetIdentifier> decode(Decoder& decoder)
|
||||
{
|
||||
auto type = TRY(decoder.decode<Web::CSS::StyleSheetIdentifier::Type>());
|
||||
auto dom_element_unique_id = TRY(decoder.decode<Optional<i32>>());
|
||||
auto url = TRY(decoder.decode<Optional<String>>());
|
||||
|
||||
return Web::CSS::StyleSheetIdentifier {
|
||||
.type = type,
|
||||
.dom_element_unique_id = move(dom_element_unique_id),
|
||||
.url = move(url),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
38
Userland/Libraries/LibWeb/CSS/StyleSheetIdentifier.h
Normal file
38
Userland/Libraries/LibWeb/CSS/StyleSheetIdentifier.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <LibURL/URL.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
struct StyleSheetIdentifier {
|
||||
enum class Type : u8 {
|
||||
StyleElement,
|
||||
LinkElement,
|
||||
ImportRule,
|
||||
UserAgent,
|
||||
UserStyle,
|
||||
} type;
|
||||
Optional<i32> dom_element_unique_id {};
|
||||
Optional<String> url {};
|
||||
};
|
||||
|
||||
StringView style_sheet_identifier_type_to_string(StyleSheetIdentifier::Type);
|
||||
Optional<StyleSheetIdentifier::Type> style_sheet_identifier_type_from_string(StringView);
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Web::CSS::StyleSheetIdentifier const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::CSS::StyleSheetIdentifier> decode(Decoder&);
|
||||
|
||||
}
|
|
@ -83,6 +83,7 @@ public:
|
|||
virtual bool is_svg_element() const { return false; }
|
||||
virtual bool is_svg_graphics_element() const { return false; }
|
||||
virtual bool is_svg_script_element() const { return false; }
|
||||
virtual bool is_svg_style_element() const { return false; }
|
||||
virtual bool is_svg_svg_element() const { return false; }
|
||||
virtual bool is_svg_use_element() const { return false; }
|
||||
|
||||
|
@ -100,8 +101,10 @@ public:
|
|||
virtual bool is_html_base_element() const { return false; }
|
||||
virtual bool is_html_body_element() const { return false; }
|
||||
virtual bool is_html_input_element() const { return false; }
|
||||
virtual bool is_html_link_element() const { return false; }
|
||||
virtual bool is_html_progress_element() const { return false; }
|
||||
virtual bool is_html_script_element() const { return false; }
|
||||
virtual bool is_html_style_element() const { return false; }
|
||||
virtual bool is_html_template_element() const { return false; }
|
||||
virtual bool is_html_table_element() const { return false; }
|
||||
virtual bool is_html_table_section_element() const { return false; }
|
||||
|
|
|
@ -200,6 +200,7 @@ class StringStyleValue;
|
|||
class StyleComputer;
|
||||
class StyleProperties;
|
||||
class StyleSheet;
|
||||
struct StyleSheetIdentifier;
|
||||
class StyleSheetList;
|
||||
class StyleValueList;
|
||||
class Supports;
|
||||
|
|
|
@ -53,7 +53,10 @@ private:
|
|||
virtual void resource_did_fail() override;
|
||||
virtual void resource_did_load() override;
|
||||
|
||||
// ^ HTMLElement
|
||||
// ^DOM::Node
|
||||
virtual bool is_html_link_element() const override { return true; }
|
||||
|
||||
// ^HTMLElement
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
struct LinkProcessingOptions {
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
private:
|
||||
HTMLStyleElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
||||
// ^DOM::Node
|
||||
virtual bool is_html_style_element() const override { return true; }
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ public:
|
|||
private:
|
||||
SVGStyleElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
||||
// ^DOM::Node
|
||||
virtual bool is_svg_style_element() const override { return true; }
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
#include <LibJS/Console.h>
|
||||
#include <LibJS/Runtime/ConsoleObject.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/CSS/CSSImportRule.h>
|
||||
#include <LibWeb/Cookie/ParsedCookie.h>
|
||||
#include <LibWeb/DOM/Attr.h>
|
||||
#include <LibWeb/DOM/NamedNodeMap.h>
|
||||
#include <LibWeb/HTML/HTMLLinkElement.h>
|
||||
#include <LibWeb/HTML/HTMLStyleElement.h>
|
||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
#include <LibWeb/Layout/Viewport.h>
|
||||
|
@ -739,6 +742,88 @@ void PageClient::did_get_js_console_messages(i32 start_index, Vector<ByteString>
|
|||
client().async_did_get_js_console_messages(m_id, start_index, move(message_types), move(messages));
|
||||
}
|
||||
|
||||
static void gather_style_sheets(Vector<Web::CSS::StyleSheetIdentifier>& results, Web::CSS::CSSStyleSheet& sheet)
|
||||
{
|
||||
Web::CSS::StyleSheetIdentifier identifier {};
|
||||
|
||||
bool valid = true;
|
||||
|
||||
if (sheet.owner_rule()) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::ImportRule;
|
||||
} else if (auto* node = sheet.owner_node()) {
|
||||
if (node->is_html_style_element() || node->is_svg_style_element()) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::StyleElement;
|
||||
} else if (is<Web::HTML::HTMLLinkElement>(node)) {
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::LinkElement;
|
||||
} else {
|
||||
dbgln("Can't identify where style sheet came from; owner node is {}", node->debug_description());
|
||||
identifier.type = Web::CSS::StyleSheetIdentifier::Type::StyleElement;
|
||||
}
|
||||
identifier.dom_element_unique_id = node->unique_id();
|
||||
} else {
|
||||
dbgln("Style sheet has no owner rule or owner node; skipping");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (auto location = sheet.location(); location.has_value())
|
||||
identifier.url = location.release_value();
|
||||
|
||||
results.append(move(identifier));
|
||||
}
|
||||
|
||||
for (auto& import_rule : sheet.import_rules()) {
|
||||
if (import_rule->loaded_style_sheet()) {
|
||||
gather_style_sheets(results, *import_rule->loaded_style_sheet());
|
||||
} else {
|
||||
// We can gather this anyway, and hope it loads later
|
||||
results.append({ .type = Web::CSS::StyleSheetIdentifier::Type::ImportRule,
|
||||
.url = MUST(import_rule->url().to_string()) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<Web::CSS::StyleSheetIdentifier> PageClient::list_style_sheets() const
|
||||
{
|
||||
Vector<Web::CSS::StyleSheetIdentifier> results;
|
||||
|
||||
auto const* document = page().top_level_browsing_context().active_document();
|
||||
if (document) {
|
||||
for (auto& sheet : document->style_sheets().sheets()) {
|
||||
gather_style_sheets(results, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
// User style
|
||||
if (page().user_style().has_value()) {
|
||||
results.append({
|
||||
.type = Web::CSS::StyleSheetIdentifier::Type::UserStyle,
|
||||
});
|
||||
}
|
||||
|
||||
// User-agent
|
||||
results.append({
|
||||
.type = Web::CSS::StyleSheetIdentifier::Type::UserAgent,
|
||||
.url = "CSS/Default.css"_string,
|
||||
});
|
||||
if (document && document->in_quirks_mode()) {
|
||||
results.append({
|
||||
.type = Web::CSS::StyleSheetIdentifier::Type::UserAgent,
|
||||
.url = "CSS/QuirksMode.css"_string,
|
||||
});
|
||||
}
|
||||
results.append({
|
||||
.type = Web::CSS::StyleSheetIdentifier::Type::UserAgent,
|
||||
.url = "MathML/Default.css"_string,
|
||||
});
|
||||
results.append({
|
||||
.type = Web::CSS::StyleSheetIdentifier::Type::UserAgent,
|
||||
.url = "SVG/Default.css"_string,
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
Web::DisplayListPlayerType PageClient::display_list_player_type() const
|
||||
{
|
||||
switch (s_use_skia_painter) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||
#include <LibWeb/HTML/AudioPlayState.h>
|
||||
#include <LibWeb/HTML/FileFilter.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
|
@ -83,6 +84,8 @@ public:
|
|||
void console_peer_did_misbehave(char const* reason);
|
||||
void did_get_js_console_messages(i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages);
|
||||
|
||||
Vector<Web::CSS::StyleSheetIdentifier> list_style_sheets() const;
|
||||
|
||||
virtual double device_pixels_per_css_pixel() const override { return m_device_pixels_per_css_pixel; }
|
||||
|
||||
virtual Web::DisplayListPlayerType display_list_player_type() const override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue