diff options
Diffstat (limited to 'components/script/webdriver_handlers.rs')
-rw-r--r-- | components/script/webdriver_handlers.rs | 134 |
1 files changed, 103 insertions, 31 deletions
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 6b4264d945e..322839aa078 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -81,7 +81,7 @@ fn find_node_by_unique_id( match documents.find_document(pipeline) { Some(doc) => find_node_by_unique_id_in_document(&doc, node_id), None => { - if ScriptThread::has_node_id(&node_id) { + if ScriptThread::has_node_id(pipeline, &node_id) { Err(ErrorStatus::StaleElementReference) } else { Err(ErrorStatus::NoSuchElement) @@ -94,14 +94,15 @@ pub(crate) fn find_node_by_unique_id_in_document( document: &Document, node_id: String, ) -> Result<DomRoot<Node>, ErrorStatus> { + let pipeline = document.window().pipeline_id(); match document .upcast::<Node>() .traverse_preorder(ShadowIncluding::Yes) - .find(|node| node.unique_id() == node_id) + .find(|node| node.unique_id(pipeline) == node_id) { Some(node) => Ok(node), None => { - if ScriptThread::has_node_id(&node_id) { + if ScriptThread::has_node_id(pipeline, &node_id) { Err(ErrorStatus::StaleElementReference) } else { Err(ErrorStatus::NoSuchElement) @@ -129,7 +130,10 @@ fn matching_links( content == link_text } }) - .map(|node| node.upcast::<Node>().unique_id()) + .map(|node| { + node.upcast::<Node>() + .unique_id(node.owner_doc().window().pipeline_id()) + }) } fn all_matching_links( @@ -329,20 +333,25 @@ unsafe fn jsval_to_webdriver_inner( Ok(WebDriverJSValue::ArrayLike(result)) } else if let Ok(element) = root_from_object::<Element>(*object, cx) { Ok(WebDriverJSValue::Element(WebElement( - element.upcast::<Node>().unique_id(), + element + .upcast::<Node>() + .unique_id(element.owner_document().window().pipeline_id()), ))) } else if let Ok(window) = root_from_object::<Window>(*object, cx) { let window_proxy = window.window_proxy(); if window_proxy.is_browsing_context_discarded() { return Err(WebDriverJSError::StaleElementReference); - } else if window_proxy.browsing_context_id() == window_proxy.webview_id() { - Ok(WebDriverJSValue::Window(WebWindow( - window.Document().upcast::<Node>().unique_id(), - ))) } else { - Ok(WebDriverJSValue::Frame(WebFrame( - window.Document().upcast::<Node>().unique_id(), - ))) + let pipeline = window.pipeline_id(); + if window_proxy.browsing_context_id() == window_proxy.webview_id() { + Ok(WebDriverJSValue::Window(WebWindow( + window.Document().upcast::<Node>().unique_id(pipeline), + ))) + } else { + Ok(WebDriverJSValue::Frame(WebFrame( + window.Document().upcast::<Node>().unique_id(pipeline), + ))) + } } } else if object_has_to_json_property(cx, global_scope, object.handle()) { let name = CString::new("toJSON").unwrap(); @@ -598,7 +607,7 @@ pub(crate) fn handle_find_element_css( .QuerySelector(DOMString::from(selector)) .map_err(|_| ErrorStatus::InvalidSelector) }) - .map(|node| node.map(|x| x.upcast::<Node>().unique_id())), + .map(|node| node.map(|x| x.upcast::<Node>().unique_id(pipeline))), ) .unwrap(); } @@ -640,7 +649,7 @@ pub(crate) fn handle_find_element_tag_name( .elements_iter() .next() }) - .map(|node| node.map(|x| x.upcast::<Node>().unique_id())), + .map(|node| node.map(|x| x.upcast::<Node>().unique_id(pipeline))), ) .unwrap(); } @@ -664,7 +673,7 @@ pub(crate) fn handle_find_elements_css( .map(|nodes| { nodes .iter() - .map(|x| x.upcast::<Node>().unique_id()) + .map(|x| x.upcast::<Node>().unique_id(pipeline)) .collect() }), ) @@ -706,7 +715,7 @@ pub(crate) fn handle_find_elements_tag_name( .map(|nodes| { nodes .elements_iter() - .map(|x| x.upcast::<Node>().unique_id()) + .map(|x| x.upcast::<Node>().unique_id(pipeline)) .collect::<Vec<String>>() }), ) @@ -725,7 +734,7 @@ pub(crate) fn handle_find_element_element_css( find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { node.query_selector(DOMString::from(selector)) .map_err(|_| ErrorStatus::InvalidSelector) - .map(|node| node.map(|x| x.upcast::<Node>().unique_id())) + .map(|node| node.map(|x| x.upcast::<Node>().unique_id(pipeline))) }), ) .unwrap(); @@ -764,7 +773,7 @@ pub(crate) fn handle_find_element_element_tag_name( .GetElementsByTagName(DOMString::from(selector), can_gc) .elements_iter() .next() - .map(|x| x.upcast::<Node>().unique_id())), + .map(|x| x.upcast::<Node>().unique_id(pipeline))), None => Err(ErrorStatus::UnknownError), }), ) @@ -786,7 +795,7 @@ pub(crate) fn handle_find_element_elements_css( .map(|nodes| { nodes .iter() - .map(|x| x.upcast::<Node>().unique_id()) + .map(|x| x.upcast::<Node>().unique_id(pipeline)) .collect() }) }), @@ -826,7 +835,7 @@ pub(crate) fn handle_find_element_elements_tag_name( Some(element) => Ok(element .GetElementsByTagName(DOMString::from(selector), can_gc) .elements_iter() - .map(|x| x.upcast::<Node>().unique_id()) + .map(|x| x.upcast::<Node>().unique_id(pipeline)) .collect::<Vec<String>>()), None => Err(ErrorStatus::UnknownError), }), @@ -834,24 +843,87 @@ pub(crate) fn handle_find_element_elements_tag_name( .unwrap(); } -pub(crate) fn handle_focus_element( +/// <https://www.w3.org/TR/webdriver2/#dfn-get-element-shadow-root> +pub(crate) fn handle_get_element_shadow_root( documents: &DocumentCollection, pipeline: PipelineId, element_id: String, - reply: IpcSender<Result<(), ErrorStatus>>, + reply: IpcSender<Result<Option<String>, ErrorStatus>>, +) { + reply + .send( + find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node + .downcast::<Element>( + ) { + Some(element) => Ok(element + .GetShadowRoot() + .map(|x| x.upcast::<Node>().unique_id(pipeline))), + None => Err(ErrorStatus::NoSuchElement), + }), + ) + .unwrap(); +} + +pub(crate) fn handle_will_send_keys( + documents: &DocumentCollection, + pipeline: PipelineId, + element_id: String, + text: String, + strict_file_interactability: bool, + reply: IpcSender<Result<bool, ErrorStatus>>, can_gc: CanGc, ) { reply .send( find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { - match node.downcast::<HTMLElement>() { - Some(element) => { - // Need a way to find if this actually succeeded - element.Focus(can_gc); - Ok(()) - }, - None => Err(ErrorStatus::UnknownError), + // Step 6: Let file be true if element is input element + // in the file upload state, or false otherwise + let file_input = node + .downcast::<HTMLInputElement>() + .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::<HTMLElement>() { + Some(element) => { + // Need a way to find if this actually succeeded + element.Focus(can_gc); + }, + None => return Err(ErrorStatus::UnknownError), + } } + + // Step 8 (file input) + if let Some(file_input) = file_input { + // Step 8.1: Let files be the result of splitting text + // on the newline (\n) character. + let files: Vec<DOMString> = text.split("\n").map(|s| s.into()).collect(); + + // Step 8.2 + if files.is_empty() { + return Err(ErrorStatus::InvalidArgument); + } + + // Step 8.3 - 8.4 + if !file_input.Multiple() && files.len() > 1 { + return Err(ErrorStatus::InvalidArgument); + } + + // Step 8.5 + // TODO: Should return invalid argument error if file doesn't exist + + // Step 8.6 - 8.7 + // Input and change event already fired in `htmlinputelement.rs`. + file_input.SelectFiles(files, can_gc); + + // Step 8.8 + return Ok(false); + } + + // TODO: Check non-typeable form control + // TODO: Check content editable + + Ok(true) }), ) .unwrap(); @@ -867,7 +939,7 @@ pub(crate) fn handle_get_active_element( documents .find_document(pipeline) .and_then(|document| document.GetActiveElement()) - .map(|element| element.upcast::<Node>().unique_id()), + .map(|element| element.upcast::<Node>().unique_id(pipeline)), ) .unwrap(); } @@ -1395,7 +1467,7 @@ pub(crate) fn handle_element_click( Ok(None) }, - None => Ok(Some(node.unique_id())), + None => Ok(Some(node.unique_id(pipeline))), } }), ) |