diff --git a/Userland/Libraries/LibWeb/HTML/AttributeNames.cpp b/Userland/Libraries/LibWeb/HTML/AttributeNames.cpp
index a9e7b64c690..2e73cb25113 100644
--- a/Userland/Libraries/LibWeb/HTML/AttributeNames.cpp
+++ b/Userland/Libraries/LibWeb/HTML/AttributeNames.cpp
@@ -41,33 +41,48 @@ void initialize_strings()
// https://html.spec.whatwg.org/#boolean-attribute
bool is_boolean_attribute(FlyString const& attribute)
{
- // NOTE: This is the list of attributes from https://html.spec.whatwg.org/#attributes-3
- // with a Value column value of "Boolean attribute".
- return attribute.is_one_of(
- AttributeNames::allowfullscreen,
- AttributeNames::async,
- AttributeNames::autofocus,
- AttributeNames::autoplay,
- AttributeNames::checked,
- AttributeNames::controls,
- AttributeNames::default_,
- AttributeNames::defer,
- AttributeNames::disabled,
- AttributeNames::formnovalidate,
- AttributeNames::inert,
- AttributeNames::ismap,
- AttributeNames::itemscope,
- AttributeNames::loop,
- AttributeNames::multiple,
- AttributeNames::muted,
- AttributeNames::nomodule,
- AttributeNames::novalidate,
- AttributeNames::open,
- AttributeNames::playsinline,
- AttributeNames::readonly,
- AttributeNames::required,
- AttributeNames::reversed,
- AttributeNames::selected);
+ // NOTE: For web compatibility, this matches the list of attributes which Chromium considers to be booleans,
+ // excluding attributes that are only used by Chromium itself:
+ // https://source.chromium.org/chromium/chromium/src/+/460b7c003cf89fc9493e721701906f19e5f6a387:chrome/test/chromedriver/element_commands.cc;l=48-94
+ return attribute.equals_ignoring_ascii_case(AttributeNames::allowfullscreen)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::async)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::autofocus)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::autoplay)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::checked)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::compact)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::controls)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::declare)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::default_)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::defaultchecked)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::defaultselected)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::defer)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::disabled)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::ended)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::formnovalidate)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::hidden)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::indeterminate)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::iscontenteditable)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::ismap)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::itemscope)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::loop)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::multiple)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::muted)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::nohref)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::nomodule)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::noresize)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::noshade)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::novalidate)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::nowrap)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::open)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::paused)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::playsinline)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::readonly)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::required)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::reversed)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::seeking)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::selected)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::truespeed)
+ || attribute.equals_ignoring_ascii_case(AttributeNames::willvalidate);
}
}
diff --git a/Userland/Libraries/LibWeb/HTML/AttributeNames.h b/Userland/Libraries/LibWeb/HTML/AttributeNames.h
index 0f2544f633c..6dc4c95cbca 100644
--- a/Userland/Libraries/LibWeb/HTML/AttributeNames.h
+++ b/Userland/Libraries/LibWeb/HTML/AttributeNames.h
@@ -60,6 +60,8 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(datetime) \
__ENUMERATE_HTML_ATTRIBUTE(declare) \
__ENUMERATE_HTML_ATTRIBUTE(default_) \
+ __ENUMERATE_HTML_ATTRIBUTE(defaultchecked) \
+ __ENUMERATE_HTML_ATTRIBUTE(defaultselected) \
__ENUMERATE_HTML_ATTRIBUTE(defer) \
__ENUMERATE_HTML_ATTRIBUTE(dir) \
__ENUMERATE_HTML_ATTRIBUTE(direction) \
@@ -67,6 +69,7 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(disabled) \
__ENUMERATE_HTML_ATTRIBUTE(download) \
__ENUMERATE_HTML_ATTRIBUTE(enctype) \
+ __ENUMERATE_HTML_ATTRIBUTE(ended) \
__ENUMERATE_HTML_ATTRIBUTE(event) \
__ENUMERATE_HTML_ATTRIBUTE(face) \
__ENUMERATE_HTML_ATTRIBUTE(fetchpriority) \
@@ -90,9 +93,11 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(id) \
__ENUMERATE_HTML_ATTRIBUTE(imagesizes) \
__ENUMERATE_HTML_ATTRIBUTE(imagesrcset) \
+ __ENUMERATE_HTML_ATTRIBUTE(indeterminate) \
__ENUMERATE_HTML_ATTRIBUTE(inert) \
__ENUMERATE_HTML_ATTRIBUTE(integrity) \
__ENUMERATE_HTML_ATTRIBUTE(is) \
+ __ENUMERATE_HTML_ATTRIBUTE(iscontenteditable) \
__ENUMERATE_HTML_ATTRIBUTE(ismap) \
__ENUMERATE_HTML_ATTRIBUTE(itemscope) \
__ENUMERATE_HTML_ATTRIBUTE(kind) \
@@ -212,6 +217,7 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(open) \
__ENUMERATE_HTML_ATTRIBUTE(optimum) \
__ENUMERATE_HTML_ATTRIBUTE(pattern) \
+ __ENUMERATE_HTML_ATTRIBUTE(paused) \
__ENUMERATE_HTML_ATTRIBUTE(ping) \
__ENUMERATE_HTML_ATTRIBUTE(placeholder) \
__ENUMERATE_HTML_ATTRIBUTE(playsinline) \
@@ -232,6 +238,7 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(scrollamount) \
__ENUMERATE_HTML_ATTRIBUTE(scrolldelay) \
__ENUMERATE_HTML_ATTRIBUTE(scrolling) \
+ __ENUMERATE_HTML_ATTRIBUTE(seeking) \
__ENUMERATE_HTML_ATTRIBUTE(selected) \
__ENUMERATE_HTML_ATTRIBUTE(shadowrootclonable) \
__ENUMERATE_HTML_ATTRIBUTE(shadowrootdelegatesfocus) \
@@ -265,6 +272,7 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(vlink) \
__ENUMERATE_HTML_ATTRIBUTE(vspace) \
__ENUMERATE_HTML_ATTRIBUTE(width) \
+ __ENUMERATE_HTML_ATTRIBUTE(willvalidate) \
__ENUMERATE_HTML_ATTRIBUTE(wrap)
#define __ENUMERATE_HTML_ATTRIBUTE(name) extern FlyString name;
diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp
index ecd32df6c1e..f230f00ae81 100644
--- a/Userland/Services/WebContent/WebDriverConnection.cpp
+++ b/Userland/Services/WebContent/WebDriverConnection.cpp
@@ -1302,36 +1302,33 @@ Messages::WebDriverClient::IsElementSelectedResponse WebDriverConnection::is_ele
// 12.4.2 Get Element Attribute, https://w3c.github.io/webdriver/#dfn-get-element-attribute
Messages::WebDriverClient::GetElementAttributeResponse WebDriverConnection::get_element_attribute(String const& element_id, String const& name)
{
- // 1. If the current browsing context is no longer open, return error with error code no such window.
+ // 1. If session's current browsing context is no longer open, return error with error code no such window.
TRY(ensure_current_browsing_context_is_open());
- // 2. Handle any user prompts and return its value if it is an error.
+ // 2. Try to handle any user prompts with session.
handle_any_user_prompts([this, element_id, name]() {
- // 3. Let element be the result of trying to get a known connected element with url variable element id.
+ // 3. Let element be the result of trying to get a known element with session and URL variables' element id.
auto element = WEBDRIVER_TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
- // 4. Let result be the result of the first matching condition:
- Optional result;
+ // 4. Let name be URL variables["name"].
+ // 5. Let result be the result of the first matching condition:
+ String result {};
// -> If name is a boolean attribute
if (Web::HTML::is_boolean_attribute(name)) {
- // "true" (string) if the element has the attribute, otherwise null.
+ // "true" (string) if the element hasAttribute() with name, otherwise null.
if (element->has_attribute(name))
- result = "true"sv;
+ result = "true"_string;
}
// -> Otherwise
else {
// The result of getting an attribute by name name.
if (auto attr = element->get_attribute(name); attr.has_value())
- result = attr->to_byte_string();
+ result = attr.release_value();
}
// 5. Return success with data result.
- if (result.has_value()) {
- async_driver_execution_complete({ result.release_value() });
- return;
- }
- async_driver_execution_complete(JsonValue {});
+ async_driver_execution_complete({ result.to_byte_string() });
});
return JsonValue {};