/src/serenity/Userland/Libraries/LibWeb/HTML/HTMLMetaElement.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, the SerenityOS developers. |
3 | | * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibWeb/Bindings/HTMLMetaElementPrototype.h> |
9 | | #include <LibWeb/Bindings/Intrinsics.h> |
10 | | #include <LibWeb/CSS/Parser/Parser.h> |
11 | | #include <LibWeb/CSS/Parser/ParsingContext.h> |
12 | | #include <LibWeb/CSS/PropertyID.h> |
13 | | #include <LibWeb/CSS/StyleValues/CSSColorValue.h> |
14 | | #include <LibWeb/DOM/Document.h> |
15 | | #include <LibWeb/HTML/HTMLMetaElement.h> |
16 | | #include <LibWeb/Infra/CharacterTypes.h> |
17 | | #include <LibWeb/Page/Page.h> |
18 | | |
19 | | namespace Web::HTML { |
20 | | |
21 | | JS_DEFINE_ALLOCATOR(HTMLMetaElement); |
22 | | |
23 | | HTMLMetaElement::HTMLMetaElement(DOM::Document& document, DOM::QualifiedName qualified_name) |
24 | 0 | : HTMLElement(document, move(qualified_name)) |
25 | 0 | { |
26 | 0 | } |
27 | | |
28 | 0 | HTMLMetaElement::~HTMLMetaElement() = default; |
29 | | |
30 | | void HTMLMetaElement::initialize(JS::Realm& realm) |
31 | 0 | { |
32 | 0 | Base::initialize(realm); |
33 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLMetaElement); |
34 | 0 | } |
35 | | |
36 | | Optional<HTMLMetaElement::HttpEquivAttributeState> HTMLMetaElement::http_equiv_state() const |
37 | 0 | { |
38 | 0 | auto value = get_attribute_value(HTML::AttributeNames::http_equiv); |
39 | |
|
40 | 0 | #define __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE(keyword, state) \ |
41 | 0 | if (value.equals_ignoring_ascii_case(keyword##sv)) \ |
42 | 0 | return HTMLMetaElement::HttpEquivAttributeState::state; |
43 | 0 | ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTES |
44 | 0 | #undef __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE |
45 | | |
46 | 0 | return OptionalNone {}; |
47 | 0 | } |
48 | | |
49 | | void HTMLMetaElement::inserted() |
50 | 0 | { |
51 | 0 | Base::inserted(); |
52 | | |
53 | | // https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color |
54 | | // 1. To obtain a page's theme color, user agents must run the following steps: |
55 | | // * The element is in a document tree |
56 | | // * The element has a name attribute, whose value is an ASCII case-insensitive match for theme-color |
57 | | // * The element has a content attribute |
58 | 0 | auto content = attribute(AttributeNames::content); |
59 | 0 | if (name().has_value() && name()->equals_ignoring_ascii_case("theme-color"sv) && content.has_value()) { |
60 | 0 | auto context = CSS::Parser::ParsingContext { document() }; |
61 | | |
62 | | // 2. For each element in candidate elements: |
63 | | |
64 | | // 1. If element has a media attribute and the value of element's media attribute does not match the environment, then continue. |
65 | 0 | auto media = attribute(AttributeNames::media); |
66 | 0 | if (media.has_value()) { |
67 | 0 | auto query = parse_media_query(context, media.value()); |
68 | 0 | if (document().window() && !query->evaluate(*document().window())) |
69 | 0 | return; |
70 | 0 | } |
71 | | |
72 | | // 2. Let value be the result of stripping leading and trailing ASCII whitespace from the value of element's content attribute. |
73 | 0 | auto value = content->bytes_as_string_view().trim(Infra::ASCII_WHITESPACE); |
74 | | |
75 | | // 3. Let color be the result of parsing value. |
76 | 0 | auto css_value = parse_css_value(context, value, CSS::PropertyID::Color); |
77 | 0 | if (css_value.is_null() || !css_value->is_color()) |
78 | 0 | return; |
79 | 0 | auto color = css_value->to_color({}); // TODO: Pass a layout node? |
80 | | |
81 | | // 4. If color is not failure, then return color. |
82 | 0 | document().page().client().page_did_change_theme_color(color); |
83 | 0 | return; |
84 | 0 | } |
85 | | |
86 | | // https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives |
87 | | // When a meta element is inserted into the document, if its http-equiv attribute is present and represents one of |
88 | | // the above states, then the user agent must run the algorithm appropriate for that state, as described in the |
89 | | // following list: |
90 | 0 | auto http_equiv = http_equiv_state(); |
91 | 0 | if (http_equiv.has_value()) { |
92 | 0 | switch (http_equiv.value()) { |
93 | 0 | case HttpEquivAttributeState::EncodingDeclaration: |
94 | | // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type |
95 | | // The Encoding declaration state is just an alternative form of setting the charset attribute: it is a character encoding declaration. |
96 | | // This state's user agent requirements are all handled by the parsing section of the specification. |
97 | 0 | break; |
98 | 0 | case HttpEquivAttributeState::Refresh: { |
99 | | // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh |
100 | | // 1. If the meta element has no content attribute, or if that attribute's value is the empty string, then return. |
101 | | // 2. Let input be the value of the element's content attribute. |
102 | 0 | if (!has_attribute(AttributeNames::content)) |
103 | 0 | break; |
104 | | |
105 | 0 | auto input = get_attribute_value(AttributeNames::content); |
106 | 0 | if (input.is_empty()) |
107 | 0 | break; |
108 | | |
109 | | // 3. Run the shared declarative refresh steps with the meta element's node document, input, and the meta element. |
110 | 0 | document().shared_declarative_refresh_steps(input, this); |
111 | 0 | break; |
112 | 0 | } |
113 | 0 | case HttpEquivAttributeState::SetCookie: |
114 | | // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-set-cookie |
115 | | // This pragma is non-conforming and has no effect. |
116 | | // User agents are required to ignore this pragma. |
117 | 0 | break; |
118 | 0 | case HttpEquivAttributeState::XUACompatible: |
119 | | // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-x-ua-compatible |
120 | | // In practice, this pragma encourages Internet Explorer to more closely follow the specifications. |
121 | | // For meta elements with an http-equiv attribute in the X-UA-Compatible state, the content attribute must have a value that is an ASCII case-insensitive match for the string "IE=edge". |
122 | | // User agents are required to ignore this pragma. |
123 | 0 | break; |
124 | 0 | default: |
125 | 0 | dbgln("FIXME: Implement '{}' http-equiv state", get_attribute_value(AttributeNames::http_equiv)); |
126 | 0 | break; |
127 | 0 | } |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | | } |