diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 822d194b0e2..9e20b09ef20 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1859,6 +1859,15 @@ impl ScriptThread { reply, ) }, + WebDriverScriptCommand::FindElementElementCSS(selector, element_id, reply) => { + webdriver_handlers::handle_find_element_element_css( + &*documents, + pipeline_id, + element_id, + selector, + reply, + ) + }, WebDriverScriptCommand::FocusElement(element_id, reply) => { webdriver_handlers::handle_focus_element( &*documents, diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 3113fb0a527..89e2df12c9d 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -203,6 +203,23 @@ pub fn handle_find_elements_css( reply.send(node_ids).unwrap(); } +pub fn handle_find_element_element_css( + documents: &Documents, + pipeline: PipelineId, + element_id: String, + selector: String, + reply: IpcSender, ()>>, +) { + let node_id = find_node_by_unique_id(documents, pipeline, element_id) + .ok_or(()) + .and_then(|node| { + node.query_selector(DOMString::from(selector)) + .map_err(|_| ()) + }) + .map(|node| node.map(|x| x.upcast::().unique_id())); + reply.send(node_id).unwrap(); +} + pub fn handle_focus_element( documents: &Documents, pipeline: PipelineId, diff --git a/components/script_traits/webdriver_msg.rs b/components/script_traits/webdriver_msg.rs index 22ccec78b77..157ea3aa7a9 100644 --- a/components/script_traits/webdriver_msg.rs +++ b/components/script_traits/webdriver_msg.rs @@ -25,6 +25,7 @@ pub enum WebDriverScriptCommand { ExecuteAsyncScript(String, IpcSender), FindElementCSS(String, IpcSender, ()>>), FindElementsCSS(String, IpcSender, ()>>), + FindElementElementCSS(String, String, IpcSender, ()>>), FocusElement(String, IpcSender>), GetActiveElement(IpcSender>), GetCookie(String, IpcSender>>>), diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index e67a185c8ae..7adf57bca9f 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -766,6 +766,42 @@ impl Handler { } } + // https://w3c.github.io/webdriver/#find-element-from-element + fn handle_find_element_element( + &self, + element: &WebElement, + parameters: &LocatorParameters, + ) -> WebDriverResult { + if parameters.using != LocatorStrategy::CSSSelector { + return Err(WebDriverError::new( + ErrorStatus::UnsupportedOperation, + "Unsupported locator strategy", + )); + } + + let (sender, receiver) = ipc::channel().unwrap(); + let cmd = WebDriverScriptCommand::FindElementElementCSS( + parameters.value.clone(), + element.id.clone(), + sender, + ); + + self.browsing_context_script_command(cmd)?; + + match receiver.recv().unwrap() { + Ok(value) => { + let value_resp = serde_json::to_value( + value.map(|x| serde_json::to_value(WebElement::new(x)).unwrap()), + )?; + Ok(WebDriverResponse::Generic(ValueResponse(value_resp))) + }, + Err(_) => Err(WebDriverError::new( + ErrorStatus::InvalidSelector, + "Invalid selector", + )), + } + } + // https://w3c.github.io/webdriver/webdriver-spec.html#get-element-rect fn handle_element_rect(&self, element: &WebElement) -> WebDriverResult { let (sender, receiver) = ipc::channel().unwrap(); @@ -1192,6 +1228,9 @@ impl WebDriverHandler for Handler { WebDriverCommand::SwitchToParentFrame => self.handle_switch_to_parent_frame(), WebDriverCommand::FindElement(ref parameters) => self.handle_find_element(parameters), WebDriverCommand::FindElements(ref parameters) => self.handle_find_elements(parameters), + WebDriverCommand::FindElementElement(ref element, ref parameters) => { + self.handle_find_element_element(element, parameters) + }, WebDriverCommand::GetNamedCookie(ref name) => self.handle_get_cookie(name), WebDriverCommand::GetCookies => self.handle_get_cookies(), WebDriverCommand::GetActiveElement => self.handle_active_element(),