diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 377828d2f07..9f10c21f419 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -520,6 +520,24 @@ impl HTMLInputElement {
self.input_type.get()
}
+ #[inline]
+ ///
+ pub(crate) fn is_nontypeable(&self) -> bool {
+ matches!(
+ self.input_type(),
+ InputType::Button |
+ InputType::Checkbox |
+ InputType::Color |
+ InputType::File |
+ InputType::Hidden |
+ InputType::Image |
+ InputType::Radio |
+ InputType::Range |
+ InputType::Reset |
+ InputType::Submit
+ )
+ }
+
#[inline]
pub(crate) fn is_submit_button(&self) -> bool {
let input_type = self.input_type.get();
@@ -2154,7 +2172,7 @@ impl HTMLInputElement {
}
// https://html.spec.whatwg.org/multipage/#concept-fe-mutable
- fn is_mutable(&self) -> bool {
+ pub(crate) fn is_mutable(&self) -> bool {
// https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable
// https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable
!(self.upcast::().disabled_state() || self.ReadOnly())
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs
index b00ad60cb8a..b30ec0b5330 100644
--- a/components/script/webdriver_handlers.rs
+++ b/components/script/webdriver_handlers.rs
@@ -71,6 +71,7 @@ use crate::dom::htmlselectelement::HTMLSelectElement;
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
use crate::dom::nodelist::NodeList;
use crate::dom::types::ShadowRoot;
+use crate::dom::validitystate::ValidationFlags;
use crate::dom::window::Window;
use crate::dom::xmlserializer::XMLSerializer;
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
@@ -1099,6 +1100,40 @@ fn handle_send_keys_file(
}
// Step 8. Return success with data null.
+ Ok(false)
+}
+
+/// We have verify previously that input element is not textual.
+fn handle_send_keys_non_typeable(
+ input_element: &HTMLInputElement,
+ text: &str,
+ can_gc: CanGc,
+) -> Result {
+ // Step 1. If element does not have an own property named value,
+ // Return ErrorStatus::ElementNotInteractable.
+ // Currently, we only support HTMLInputElement for non-typeable
+ // form controls. Hence, it should always have value property.
+
+ // Step 2. If element is not mutable, return ErrorStatus::ElementNotInteractable.
+ if !input_element.is_mutable() {
+ return Err(ErrorStatus::ElementNotInteractable);
+ }
+
+ // Step 3. Set a property value to text on element.
+ if input_element.SetValue(text.into(), can_gc).is_err() {
+ return Err(ErrorStatus::UnknownError);
+ }
+
+ // Step 4. If element is suffering from bad input, return ErrorStatus::InvalidArgument.
+ if input_element
+ .Validity()
+ .invalid_flags()
+ .contains(ValidationFlags::BAD_INPUT)
+ {
+ return Err(ErrorStatus::InvalidArgument);
+ }
+
+ // Step 5. Return success with data null.
// This is done in `webdriver_server:lib.rs`
Ok(false)
}
@@ -1121,10 +1156,11 @@ pub(crate) fn handle_will_send_keys(
.send(
// Set 5. Let element be the result of trying to get a known element.
get_known_element(documents, pipeline, element_id).and_then(|element| {
- // Step 6. Let file be true if element is input element
+ let input_element = element.downcast::();
+
+ // Step 6: Let file be true if element is input element
// in the file upload state, or false otherwise
- let file_input = element
- .downcast::()
+ let file_input = input_element
.filter(|&input_element| input_element.input_type() == InputType::File);
// Step 7. If file is false or the session's strict file interactability
@@ -1148,7 +1184,13 @@ pub(crate) fn handle_will_send_keys(
return handle_send_keys_file(file_input, &text, can_gc);
}
- // TODO: Check non-typeable form control
+ // Step 8 (non-typeable form control)
+ if let Some(input_element) = input_element {
+ if input_element.is_nontypeable() {
+ return handle_send_keys_non_typeable(input_element, &text, can_gc);
+ }
+ }
+
// TODO: Check content editable
Ok(true)