diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index a81c9396da7..e31a79a49e7 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -72,17 +72,24 @@ use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; use crate::script_thread::ScriptThread; /// -fn find_node_by_unique_id( +fn get_known_element( documents: &DocumentCollection, pipeline: PipelineId, node_id: String, -) -> Result, ErrorStatus> { +) -> Result, ErrorStatus> { let doc = documents .find_document(pipeline) .expect("webdriver_handlers::Document should exists"); - find_node_by_unique_id_in_document(&doc, node_id) + // Step 3. If node is not null and node does not implement Element + // return error with error code no such element. + find_node_by_unique_id_in_document(&doc, node_id).and_then(|node| { + node.downcast::() + .map(DomRoot::from_ref) + .ok_or(ErrorStatus::NoSuchElement) + }) } +// This is also used by `dom/window.rs` pub(crate) fn find_node_by_unique_id_in_document( document: &Document, node_id: String, @@ -526,8 +533,9 @@ pub(crate) fn handle_get_browsing_context_id( Err(ErrorStatus::UnsupportedOperation) }, WebDriverFrameId::Element(element_id) => { - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { - node.downcast::() + get_known_element(documents, pipeline, element_id).and_then(|element| { + element + .downcast::() .and_then(|element| element.browsing_context_id()) .ok_or(ErrorStatus::NoSuchFrame) }) @@ -588,9 +596,8 @@ pub(crate) fn handle_get_element_in_view_center_point( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).map(|node| { - get_element_in_view_center_point(node.downcast::().unwrap(), can_gc) - .map(|point| (point.x, point.y)) + get_known_element(documents, pipeline, element_id).map(|element| { + get_element_in_view_center_point(&element, can_gc).map(|point| (point.x, point.y)) }), ) .unwrap(); @@ -627,7 +634,7 @@ pub(crate) fn handle_find_element_css( document .QuerySelector(DOMString::from(selector)) .map_err(|_| ErrorStatus::InvalidSelector) - .map(|node| node.map(|x| x.upcast::().unique_id(pipeline))), + .map(|element| element.map(|x| x.upcast::().unique_id(pipeline))), ) .unwrap(), Err(error) => reply.send(Err(error)).unwrap(), @@ -668,7 +675,7 @@ pub(crate) fn handle_find_element_tag_name( .GetElementsByTagName(DOMString::from(selector), can_gc) .elements_iter() .next() - .map(|node| node.upcast::().unique_id(pipeline)))) + .map(|element| element.upcast::().unique_id(pipeline)))) .unwrap(), Err(error) => reply.send(Err(error)).unwrap(), } @@ -747,10 +754,12 @@ pub(crate) fn handle_find_element_element_css( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { - node.query_selector(DOMString::from(selector)) + get_known_element(documents, pipeline, element_id).and_then(|element| { + element + .upcast::() + .query_selector(DOMString::from(selector)) .map_err(|_| ErrorStatus::InvalidSelector) - .map(|node| node.map(|x| x.upcast::().unique_id(pipeline))) + .map(|element| element.map(|x| x.upcast::().unique_id(pipeline))) }), ) .unwrap(); @@ -767,8 +776,9 @@ pub(crate) fn handle_find_element_element_link_text( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id) - .and_then(|node| first_matching_link(&node, selector.clone(), partial, can_gc)), + get_known_element(documents, pipeline, element_id).and_then(|element| { + first_matching_link(element.upcast::(), selector.clone(), partial, can_gc) + }), ) .unwrap(); } @@ -783,15 +793,12 @@ pub(crate) fn handle_find_element_element_tag_name( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node - .downcast::( - ) { - Some(element) => Ok(element + get_known_element(documents, pipeline, element_id).map(|element| { + element .GetElementsByTagName(DOMString::from(selector), can_gc) .elements_iter() .next() - .map(|x| x.upcast::().unique_id(pipeline))), - None => Err(ErrorStatus::UnknownError), + .map(|x| x.upcast::().unique_id(pipeline)) }), ) .unwrap(); @@ -806,8 +813,10 @@ pub(crate) fn handle_find_element_elements_css( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { - node.query_selector_all(DOMString::from(selector)) + get_known_element(documents, pipeline, element_id).and_then(|element| { + element + .upcast::() + .query_selector_all(DOMString::from(selector)) .map_err(|_| ErrorStatus::InvalidSelector) .map(|nodes| { nodes @@ -831,8 +840,9 @@ pub(crate) fn handle_find_element_elements_link_text( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id) - .and_then(|node| all_matching_links(&node, selector.clone(), partial, can_gc)), + get_known_element(documents, pipeline, element_id).and_then(|element| { + all_matching_links(element.upcast::(), selector.clone(), partial, can_gc) + }), ) .unwrap(); } @@ -847,15 +857,12 @@ pub(crate) fn handle_find_element_elements_tag_name( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node - .downcast::( - ) { - Some(element) => Ok(element + get_known_element(documents, pipeline, element_id).map(|element| { + element .GetElementsByTagName(DOMString::from(selector), can_gc) .elements_iter() .map(|x| x.upcast::().unique_id(pipeline)) - .collect::>()), - None => Err(ErrorStatus::UnknownError), + .collect::>() }), ) .unwrap(); @@ -870,13 +877,10 @@ pub(crate) fn handle_get_element_shadow_root( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node - .downcast::( - ) { - Some(element) => Ok(element + get_known_element(documents, pipeline, element_id).map(|element| { + element .GetShadowRoot() - .map(|x| x.upcast::().unique_id(pipeline))), - None => Err(ErrorStatus::NoSuchElement), + .map(|x| x.upcast::().unique_id(pipeline)) }), ) .unwrap(); @@ -893,16 +897,16 @@ pub(crate) fn handle_will_send_keys( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { + get_known_element(documents, pipeline, element_id).and_then(|element| { // Step 6: Let file be true if element is input element // in the file upload state, or false otherwise - let file_input = node + let file_input = element .downcast::() .filter(|&input_element| input_element.input_type() == InputType::File); // Step 7: If file is false or the session's strict file interactability if file_input.is_none() || strict_file_interactability { - match node.downcast::() { + match element.downcast::() { Some(element) => { // Need a way to find if this actually succeeded element.Focus(can_gc); @@ -970,12 +974,8 @@ pub(crate) fn handle_get_computed_role( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id).and_then(|node| { - match node.downcast::() { - Some(element) => Ok(element.GetRole().map(String::from)), - None => Err(ErrorStatus::UnknownError), - } - }), + get_known_element(documents, pipeline, node_id) + .map(|element| element.GetRole().map(String::from)), ) .unwrap(); } @@ -1181,9 +1181,9 @@ pub(crate) fn handle_get_rect( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { + get_known_element(documents, pipeline, element_id).and_then(|element| { // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position - match node.downcast::() { + match element.downcast::() { Some(html_element) => { // Step 1 let mut x = 0; @@ -1227,17 +1227,12 @@ pub(crate) fn handle_get_bounding_client_rect( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node - .downcast::( - ) { - Some(element) => { - let rect = element.GetBoundingClientRect(can_gc); - Ok(Rect::new( - Point2D::new(rect.X() as f32, rect.Y() as f32), - Size2D::new(rect.Width() as f32, rect.Height() as f32), - )) - }, - None => Err(ErrorStatus::UnknownError), + get_known_element(documents, pipeline, element_id).map(|element| { + let rect = element.GetBoundingClientRect(can_gc); + Rect::new( + Point2D::new(rect.X() as f32, rect.Y() as f32), + Size2D::new(rect.Width() as f32, rect.Height() as f32), + ) }), ) .unwrap(); @@ -1253,10 +1248,16 @@ pub(crate) fn handle_get_text( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id).map(|node| { - node.downcast::() - .map(|element| element.InnerText(can_gc).to_string()) - .unwrap_or_else(|| node.GetTextContent().map_or("".to_owned(), String::from)) + get_known_element(documents, pipeline, node_id).map(|element| { + element + .downcast::() + .map(|htmlelement| htmlelement.InnerText(can_gc).to_string()) + .unwrap_or_else(|| { + element + .upcast::() + .GetTextContent() + .map_or("".to_owned(), String::from) + }) }), ) .unwrap(); @@ -1270,8 +1271,8 @@ pub(crate) fn handle_get_name( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id) - .map(|node| String::from(node.downcast::().unwrap().TagName())), + get_known_element(documents, pipeline, node_id) + .map(|element| String::from(element.TagName())), ) .unwrap(); } @@ -1285,9 +1286,8 @@ pub(crate) fn handle_get_attribute( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id).map(|node| { - node.downcast::() - .unwrap() + get_known_element(documents, pipeline, node_id).map(|element| { + element .GetAttribute(DOMString::from(name)) .map(String::from) }), @@ -1306,7 +1306,7 @@ pub(crate) fn handle_get_property( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id).map(|node| { + get_known_element(documents, pipeline, node_id).map(|element| { let document = documents.find_document(pipeline).unwrap(); let realm = enter_realm(&*document); let cx = document.window().get_cx(); @@ -1315,7 +1315,7 @@ pub(crate) fn handle_get_property( match unsafe { get_property_jsval( *cx, - node.reflector().get_jsobject(), + element.reflector().get_jsobject(), &name, property.handle_mut(), ) @@ -1323,7 +1323,7 @@ pub(crate) fn handle_get_property( Ok(_) => { match jsval_to_webdriver( cx, - &node.global(), + &element.global(), property.handle(), InRealm::entered(&realm), can_gc, @@ -1333,7 +1333,7 @@ pub(crate) fn handle_get_property( } }, Err(error) => { - throw_dom_exception(cx, &node.global(), error, can_gc); + throw_dom_exception(cx, &element.global(), error, can_gc); WebDriverJSValue::Undefined }, } @@ -1352,12 +1352,11 @@ pub(crate) fn handle_get_css( ) { reply .send( - find_node_by_unique_id(documents, pipeline, node_id).map(|node| { - let window = node.owner_window(); - let element = node.downcast::().unwrap(); + get_known_element(documents, pipeline, node_id).map(|element| { + let window = element.owner_window(); String::from( window - .GetComputedStyle(element, None) + .GetComputedStyle(&element, None) .GetPropertyValue(DOMString::from(name), can_gc), ) }), @@ -1422,15 +1421,15 @@ pub(crate) fn handle_element_click( reply .send( // Step 3 - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { + get_known_element(documents, pipeline, element_id).and_then(|element| { // Step 4 - if let Some(input_element) = node.downcast::() { + if let Some(input_element) = element.downcast::() { if input_element.input_type() == InputType::File { return Err(ErrorStatus::InvalidArgument); } } - let Some(container) = get_container(&node) else { + let Some(container) = get_container(element.upcast::()) else { return Err(ErrorStatus::UnknownError); }; @@ -1444,7 +1443,7 @@ pub(crate) fn handle_element_click( // TODO: return error if obscured // Step 8 - match node.downcast::() { + match element.downcast::() { Some(option_element) => { // Steps 8.2 - 8.4 let event_target = container.upcast::(); @@ -1488,7 +1487,7 @@ pub(crate) fn handle_element_click( Ok(None) }, - None => Ok(Some(node.unique_id(pipeline))), + None => Ok(Some(element.upcast::().unique_id(pipeline))), } }), ) @@ -1503,12 +1502,8 @@ pub(crate) fn handle_is_enabled( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node - .downcast::( - ) { - Some(element) => Ok(element.enabled_state()), - None => Err(ErrorStatus::UnknownError), - }), + get_known_element(documents, pipeline, element_id) + .map(|element| element.enabled_state()), ) .unwrap(); } @@ -1521,12 +1516,12 @@ pub(crate) fn handle_is_selected( ) { reply .send( - find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { - if let Some(input_element) = node.downcast::() { + get_known_element(documents, pipeline, element_id).and_then(|element| { + if let Some(input_element) = element.downcast::() { Ok(input_element.Checked()) - } else if let Some(option_element) = node.downcast::() { + } else if let Some(option_element) = element.downcast::() { Ok(option_element.Selected()) - } else if node.is::() { + } else if element.is::() { Ok(false) // regular elements are not selectable } else { Err(ErrorStatus::UnknownError)