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) =|