HTMLMetaElement.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. #include <LibWeb/Bindings/Intrinsics.h>
  8. #include <LibWeb/CSS/Parser/Parser.h>
  9. #include <LibWeb/CSS/Parser/ParsingContext.h>
  10. #include <LibWeb/CSS/PropertyID.h>
  11. #include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
  12. #include <LibWeb/DOM/Document.h>
  13. #include <LibWeb/HTML/HTMLMetaElement.h>
  14. #include <LibWeb/Infra/CharacterTypes.h>
  15. #include <LibWeb/Page/Page.h>
  16. namespace Web::HTML {
  17. JS_DEFINE_ALLOCATOR(HTMLMetaElement);
  18. HTMLMetaElement::HTMLMetaElement(DOM::Document& document, DOM::QualifiedName qualified_name)
  19. : HTMLElement(document, move(qualified_name))
  20. {
  21. }
  22. HTMLMetaElement::~HTMLMetaElement() = default;
  23. void HTMLMetaElement::initialize(JS::Realm& realm)
  24. {
  25. Base::initialize(realm);
  26. set_prototype(&Bindings::ensure_web_prototype<Bindings::HTMLMetaElementPrototype>(realm, "HTMLMetaElement"));
  27. }
  28. Optional<HTMLMetaElement::HttpEquivAttributeState> HTMLMetaElement::http_equiv_state() const
  29. {
  30. auto value = deprecated_attribute(HTML::AttributeNames::http_equiv);
  31. #define __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE(keyword, state) \
  32. if (value.equals_ignoring_ascii_case(#keyword##sv)) \
  33. return HTMLMetaElement::HttpEquivAttributeState::state;
  34. ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTES
  35. #undef __ENUMERATE_HTML_META_HTTP_EQUIV_ATTRIBUTE
  36. return OptionalNone {};
  37. }
  38. void HTMLMetaElement::inserted()
  39. {
  40. Base::inserted();
  41. // https://html.spec.whatwg.org/multipage/semantics.html#meta-theme-color
  42. // 1. To obtain a page's theme color, user agents must run the following steps:
  43. // * The element is in a document tree
  44. // * The element has a name attribute, whose value is an ASCII case-insensitive match for theme-color
  45. // * The element has a content attribute
  46. auto name = attribute(AttributeNames::name);
  47. auto content = attribute(AttributeNames::content);
  48. if (name.has_value() && name->bytes_as_string_view().equals_ignoring_ascii_case("theme-color"sv) && content.has_value()) {
  49. auto* page = document().page();
  50. if (!page)
  51. return;
  52. auto context = CSS::Parser::ParsingContext { document() };
  53. // 2. For each element in candidate elements:
  54. // 1. If element has a media attribute and the value of element's media attribute does not match the environment, then continue.
  55. auto media = attribute(AttributeNames::media);
  56. if (media.has_value()) {
  57. auto query = parse_media_query(context, media.value());
  58. if (!query->evaluate(document().window()))
  59. return;
  60. }
  61. // 2. Let value be the result of stripping leading and trailing ASCII whitespace from the value of element's content attribute.
  62. auto value = content->bytes_as_string_view().trim(Infra::ASCII_WHITESPACE);
  63. // 3. Let color be the result of parsing value.
  64. auto css_value = parse_css_value(context, value, CSS::PropertyID::Color);
  65. if (css_value.is_null() || !css_value->is_color())
  66. return;
  67. auto color = css_value->as_color().color();
  68. // 4. If color is not failure, then return color.
  69. page->client().page_did_change_theme_color(color);
  70. return;
  71. }
  72. // https://html.spec.whatwg.org/multipage/semantics.html#pragma-directives
  73. // When a meta element is inserted into the document, if its http-equiv attribute is present and represents one of
  74. // the above states, then the user agent must run the algorithm appropriate for that state, as described in the
  75. // following list:
  76. auto http_equiv = http_equiv_state();
  77. if (http_equiv.has_value()) {
  78. switch (http_equiv.value()) {
  79. case HttpEquivAttributeState::Refresh: {
  80. // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
  81. // 1. If the meta element has no content attribute, or if that attribute's value is the empty string, then return.
  82. // 2. Let input be the value of the element's content attribute.
  83. if (!has_attribute(AttributeNames::content))
  84. break;
  85. auto input = deprecated_attribute(AttributeNames::content);
  86. if (input.is_empty())
  87. break;
  88. // 3. Run the shared declarative refresh steps with the meta element's node document, input, and the meta element.
  89. document().shared_declarative_refresh_steps(input, this);
  90. break;
  91. }
  92. default:
  93. dbgln("FIXME: Implement '{}' http-equiv state", deprecated_attribute(AttributeNames::http_equiv));
  94. break;
  95. }
  96. }
  97. }
  98. }