LibWeb: Implement HTMLOrSVGElement.nonce

There are two FIXMEs remaining that depend on a functional
PolicyContainer, which we ignore for now and always behave like a CSP is
set.
This commit is contained in:
Jelle Raaijmakers 2024-10-29 13:27:01 +01:00
commit 84fe8d675b
Notes: github-actions[bot] 2024-10-31 09:47:17 +00:00
12 changed files with 174 additions and 7 deletions

View file

@ -119,6 +119,7 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(name) \
__ENUMERATE_HTML_ATTRIBUTE(nohref) \
__ENUMERATE_HTML_ATTRIBUTE(nomodule) \
__ENUMERATE_HTML_ATTRIBUTE(nonce) \
__ENUMERATE_HTML_ATTRIBUTE(noresize) \
__ENUMERATE_HTML_ATTRIBUTE(noshade) \
__ENUMERATE_HTML_ATTRIBUTE(novalidate) \

View file

@ -576,6 +576,25 @@ void HTMLElement::attribute_changed(FlyString const& name, Optional<String> cons
#undef __ENUMERATE
}
void HTMLElement::attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)
{
Base::attribute_change_steps(local_name, old_value, value, namespace_);
HTMLOrSVGElement::attribute_change_steps(local_name, old_value, value, namespace_);
}
WebIDL::ExceptionOr<void> HTMLElement::cloned(Web::DOM::Node& copy, bool clone_children)
{
TRY(Base::cloned(copy, clone_children));
TRY(HTMLOrSVGElement::cloned(copy, clone_children));
return {};
}
void HTMLElement::inserted()
{
Base::inserted();
HTMLOrSVGElement::inserted();
}
// https://html.spec.whatwg.org/multipage/webappapis.html#fire-a-synthetic-pointer-event
bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Element& target, bool not_trusted)
{

View file

@ -82,6 +82,9 @@ protected:
virtual void initialize(JS::Realm&) override;
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value) override;
virtual void attribute_change_steps(FlyString const&, Optional<String> const&, Optional<String> const&, Optional<FlyString> const&) override;
virtual WebIDL::ExceptionOr<void> cloned(DOM::Node&, bool) override;
virtual void inserted() override;
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -56,6 +56,61 @@ void HTMLOrSVGElement<ElementBase>::blur()
// User agents may selectively or uniformly ignore calls to this method for usability reasons.
}
// https://html.spec.whatwg.org/#dom-noncedelement-nonce
template<typename ElementBase>
void HTMLOrSVGElement<ElementBase>::attribute_change_steps(FlyString const& local_name, Optional<String> const&, Optional<String> const& value, Optional<FlyString> const& namespace_)
{
// 1. If element does not include HTMLOrSVGElement, then return.
// 2. If localName is not nonce or namespace is not null, then return.
if (local_name != HTML::AttributeNames::nonce || namespace_.has_value())
return;
// 3. If value is null, then set element's [[CryptographicNonce]] to the empty string.
if (!value.has_value()) {
m_cryptographic_nonce = {};
}
// 4. Otherwise, set element's [[CryptographicNonce]] to value.
else {
m_cryptographic_nonce = value.value();
}
}
// https://html.spec.whatwg.org/#dom-noncedelement-nonce
template<typename ElementBase>
WebIDL::ExceptionOr<void> HTMLOrSVGElement<ElementBase>::cloned(DOM::Node& copy, bool)
{
// The cloning steps for elements that include HTMLOrSVGElement must set the
// [[CryptographicNonce]] slot on the copy to the value of the slot on the element being cloned.
static_cast<ElementBase&>(copy).m_cryptographic_nonce = m_cryptographic_nonce;
return {};
}
// https://html.spec.whatwg.org/#dom-noncedelement-nonce
template<typename ElementBase>
void HTMLOrSVGElement<ElementBase>::inserted()
{
// Whenever an element including HTMLOrSVGElement becomes browsing-context connected, the user
// agent must execute the following steps on the element:
DOM::Element& element = *static_cast<ElementBase*>(this);
// FIXME: 1. Let CSP list be element's shadow-including root's policy container's CSP list.
[[maybe_unused]] auto policy_container = element.shadow_including_root().document().policy_container();
// FIXME: 2. If CSP list contains a header-delivered Content Security Policy, and element has a
// nonce content attribute attr whose value is not the empty string, then:
if (true && element.has_attribute(HTML::AttributeNames::nonce)) {
// 2.1. Let nonce be element's [[CryptographicNonce]].
auto nonce = m_cryptographic_nonce;
// 2.2. Set an attribute value for element using "nonce" and the empty string.
element.set_attribute_value(HTML::AttributeNames::nonce, {});
// 2.3. Set element's [[CryptographicNonce]] to nonce.
m_cryptographic_nonce = nonce;
}
}
template<typename ElementBase>
void HTMLOrSVGElement<ElementBase>::visit_edges(JS::Cell::Visitor& visitor)
{

View file

@ -17,15 +17,25 @@ class HTMLOrSVGElement {
public:
[[nodiscard]] JS::NonnullGCPtr<DOMStringMap> dataset();
// https://html.spec.whatwg.org/#dom-noncedelement-nonce
String const& nonce() { return m_cryptographic_nonce; }
void set_nonce(String const& nonce) { m_cryptographic_nonce = nonce; }
void focus();
void blur();
protected:
void attribute_change_steps(FlyString const&, Optional<String> const&, Optional<String> const&, Optional<FlyString> const&);
WebIDL::ExceptionOr<void> cloned(DOM::Node&, bool);
void inserted();
void visit_edges(JS::Cell::Visitor&);
// https://html.spec.whatwg.org/multipage/dom.html#dom-dataset-dev
JS::GCPtr<DOMStringMap> m_dataset;
// https://html.spec.whatwg.org/#cryptographicnonce
String m_cryptographic_nonce;
// https://html.spec.whatwg.org/multipage/interaction.html#locked-for-focus
bool m_locked_for_focus { false };
};

View file

@ -1,7 +1,7 @@
// https://html.spec.whatwg.org/#htmlorsvgelement
interface mixin HTMLOrSVGElement {
[SameObject] readonly attribute DOMStringMap dataset;
[FIXME] attribute DOMString nonce; // intentionally no [CEReactions]
attribute DOMString nonce; // intentionally no [CEReactions]
[CEReactions, Reflect] attribute boolean autofocus;
[CEReactions] attribute long tabIndex;