diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp
index 4208760bf5..12bd3c2a0a 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp
@@ -6,8 +6,14 @@
*/
#include
+#include
+#include
+#include
+#include
#include
#include
+#include
+#include
namespace Web::HTML {
@@ -41,6 +47,43 @@ void HTMLMetaElement::inserted()
{
Base::inserted();
+ // https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color
+ // 1. To obtain a page's theme color, user agents must run the following steps:
+ // * The element is in a document tree
+ // * The element has a name attribute, whose value is an ASCII case-insensitive match for theme-color
+ // * The element has a content attribute
+ auto name = attribute(AttributeNames::name);
+ auto content = attribute(AttributeNames::content);
+ if (name.has_value() && name->bytes_as_string_view().equals_ignoring_ascii_case("theme-color"sv) && content.has_value()) {
+ auto* page = document().page();
+ if (!page)
+ return;
+ auto context = CSS::Parser::ParsingContext { document() };
+
+ // 2. For each element in candidate elements:
+
+ // 1. If element has a media attribute and the value of element's media attribute does not match the environment, then continue.
+ auto media = attribute(AttributeNames::media);
+ if (media.has_value()) {
+ auto query = parse_media_query(context, media.value());
+ if (!query->evaluate(document().window()))
+ return;
+ }
+
+ // 2. Let value be the result of stripping leading and trailing ASCII whitespace from the value of element's content attribute.
+ auto value = content->bytes_as_string_view().trim(Infra::ASCII_WHITESPACE);
+
+ // 3. Let color be the result of parsing value.
+ auto css_value = parse_css_value(context, value, CSS::PropertyID::Color);
+ if (css_value.is_null() || !css_value->is_color())
+ return;
+ auto color = css_value->as_color().color();
+
+ // 4. If color is not failure, then return color.
+ page->client().page_did_change_theme_color(color);
+ return;
+ }
+
// https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives
// When a meta element is inserted into the document, if its http-equiv attribute is present and represents one of
// the above states, then the user agent must run the algorithm appropriate for that state, as described in the
diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h
index 4ce02b4736..701c3493f1 100644
--- a/Userland/Libraries/LibWeb/Page/Page.h
+++ b/Userland/Libraries/LibWeb/Page/Page.h
@@ -256,6 +256,8 @@ public:
virtual void page_did_finish_text_test() {};
+ virtual void page_did_change_theme_color(Gfx::Color) { }
+
protected:
virtual ~PageClient() = default;
};
diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h
index 34bcfca32a..ccbba54d97 100644
--- a/Userland/Libraries/LibWebView/ViewImplementation.h
+++ b/Userland/Libraries/LibWebView/ViewImplementation.h
@@ -154,6 +154,7 @@ public:
Function on_request_color_picker;
Function on_finish_handling_input_event;
Function on_text_test_finish;
+ Function on_theme_color_change;
virtual Gfx::IntRect viewport_rect() const = 0;
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp
index 304030c91c..41ce3cb42c 100644
--- a/Userland/Libraries/LibWebView/WebContentClient.cpp
+++ b/Userland/Libraries/LibWebView/WebContentClient.cpp
@@ -396,4 +396,10 @@ void WebContentClient::did_finish_handling_input_event(bool event_was_accepted)
m_view.on_finish_handling_input_event(event_was_accepted);
}
+void WebContentClient::did_change_theme_color(Gfx::Color color)
+{
+ if (m_view.on_theme_color_change)
+ m_view.on_theme_color_change(color);
+}
+
}
diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h
index c90615e771..57864a0e0b 100644
--- a/Userland/Libraries/LibWebView/WebContentClient.h
+++ b/Userland/Libraries/LibWebView/WebContentClient.h
@@ -85,6 +85,7 @@ private:
virtual void did_request_color_picker(Color const& current_color) override;
virtual void did_finish_handling_input_event(bool event_was_accepted) override;
virtual void did_finish_text_test() override;
+ virtual void did_change_theme_color(Gfx::Color color) override;
ViewImplementation& m_view;
};
diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp
index 45b3bbf6d0..ee591d58e7 100644
--- a/Userland/Services/WebContent/PageHost.cpp
+++ b/Userland/Services/WebContent/PageHost.cpp
@@ -463,4 +463,9 @@ void PageHost::page_did_request_color_picker(Color current_color)
m_client.async_did_request_color_picker(current_color);
}
+void PageHost::page_did_change_theme_color(Gfx::Color color)
+{
+ m_client.async_did_change_theme_color(color);
+}
+
}
diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h
index 0d73bff31c..0042baa990 100644
--- a/Userland/Services/WebContent/PageHost.h
+++ b/Userland/Services/WebContent/PageHost.h
@@ -116,6 +116,7 @@ private:
virtual void request_file(Web::FileRequest) override;
virtual void page_did_request_color_picker(Color current_color) override;
virtual void page_did_finish_text_test() override;
+ virtual void page_did_change_theme_color(Gfx::Color color) override;
explicit PageHost(ConnectionFromClient&);
diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc
index 854542157b..4648ee1dbb 100644
--- a/Userland/Services/WebContent/WebContentClient.ipc
+++ b/Userland/Services/WebContent/WebContentClient.ipc
@@ -1,5 +1,6 @@
#include
#include
+#include
#include
#include
#include
@@ -61,6 +62,7 @@ endpoint WebContentClient
did_request_file(DeprecatedString path, i32 request_id) =|
did_request_color_picker(Color current_color) =|
did_finish_handling_input_event(bool event_was_accepted) =|
+ did_change_theme_color(Gfx::Color color) =|
did_output_js_console_message(i32 message_index) =|
did_get_js_console_messages(i32 start_index, Vector message_types, Vector messages) =|