diff options
Diffstat (limited to 'components/script/webdriver_handlers.rs')
-rw-r--r-- | components/script/webdriver_handlers.rs | 566 |
1 files changed, 331 insertions, 235 deletions
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index f02f0015478..6c3e7deb910 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -38,13 +38,17 @@ use script_traits::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriver use script_traits::webdriver_msg::WebDriverCookieError; use servo_url::ServoUrl; -fn find_node_by_unique_id(documents: &Documents, - pipeline: PipelineId, - node_id: String) - -> Option<DomRoot<Node>> { - documents.find_document(pipeline).and_then(|document| - document.upcast::<Node>().traverse_preorder().find(|candidate| candidate.unique_id() == node_id) - ) +fn find_node_by_unique_id( + documents: &Documents, + pipeline: PipelineId, + node_id: String, +) -> Option<DomRoot<Node>> { + documents.find_document(pipeline).and_then(|document| { + document + .upcast::<Node>() + .traverse_preorder() + .find(|candidate| candidate.unique_id() == node_id) + }) } #[allow(unsafe_code)] @@ -54,17 +58,21 @@ pub unsafe fn jsval_to_webdriver(cx: *mut JSContext, val: HandleValue) -> WebDri } else if val.get().is_boolean() { Ok(WebDriverJSValue::Boolean(val.get().to_boolean())) } else if val.get().is_double() || val.get().is_int32() { - Ok(WebDriverJSValue::Number(match FromJSValConvertible::from_jsval(cx, val, ()).unwrap() { - ConversionResult::Success(c) => c, - _ => unreachable!(), - })) + Ok(WebDriverJSValue::Number( + match FromJSValConvertible::from_jsval(cx, val, ()).unwrap() { + ConversionResult::Success(c) => c, + _ => unreachable!(), + }, + )) } else if val.get().is_string() { //FIXME: use jsstring_to_str when jsval grows to_jsstring - let string: DOMString = match FromJSValConvertible::from_jsval(cx, val, StringificationBehavior::Default) - .unwrap() { - ConversionResult::Success(c) => c, - _ => unreachable!(), - }; + let string: DOMString = + match FromJSValConvertible::from_jsval(cx, val, StringificationBehavior::Default) + .unwrap() + { + ConversionResult::Success(c) => c, + _ => unreachable!(), + }; Ok(WebDriverJSValue::String(String::from(string))) } else if val.get().is_null() { Ok(WebDriverJSValue::Null) @@ -74,124 +82,174 @@ pub unsafe fn jsval_to_webdriver(cx: *mut JSContext, val: HandleValue) -> WebDri } #[allow(unsafe_code)] -pub fn handle_execute_script(documents: &Documents, - pipeline: PipelineId, - eval: String, - reply: IpcSender<WebDriverJSResult>) { +pub fn handle_execute_script( + documents: &Documents, + pipeline: PipelineId, + eval: String, + reply: IpcSender<WebDriverJSResult>, +) { let window = match documents.find_window(pipeline) { Some(window) => window, - None => return reply.send(Err(WebDriverJSError::BrowsingContextNotFound)).unwrap() + None => { + return reply + .send(Err(WebDriverJSError::BrowsingContextNotFound)) + .unwrap() + }, }; let result = unsafe { let cx = window.get_cx(); rooted!(in(cx) let mut rval = UndefinedValue()); - window.upcast::<GlobalScope>().evaluate_js_on_global_with_result( - &eval, rval.handle_mut()); + window + .upcast::<GlobalScope>() + .evaluate_js_on_global_with_result(&eval, rval.handle_mut()); jsval_to_webdriver(cx, rval.handle()) }; reply.send(result).unwrap(); } -pub fn handle_execute_async_script(documents: &Documents, - pipeline: PipelineId, - eval: String, - reply: IpcSender<WebDriverJSResult>) { +pub fn handle_execute_async_script( + documents: &Documents, + pipeline: PipelineId, + eval: String, + reply: IpcSender<WebDriverJSResult>, +) { let window = match documents.find_window(pipeline) { - Some(window) => window, - None => return reply.send(Err(WebDriverJSError::BrowsingContextNotFound)).unwrap() + Some(window) => window, + None => { + return reply + .send(Err(WebDriverJSError::BrowsingContextNotFound)) + .unwrap() + }, }; let cx = window.get_cx(); window.set_webdriver_script_chan(Some(reply)); rooted!(in(cx) let mut rval = UndefinedValue()); - window.upcast::<GlobalScope>().evaluate_js_on_global_with_result(&eval, rval.handle_mut()); + window + .upcast::<GlobalScope>() + .evaluate_js_on_global_with_result(&eval, rval.handle_mut()); } -pub fn handle_get_browsing_context_id(documents: &Documents, - pipeline: PipelineId, - webdriver_frame_id: WebDriverFrameId, - reply: IpcSender<Result<BrowsingContextId, ()>>) { +pub fn handle_get_browsing_context_id( + documents: &Documents, + pipeline: PipelineId, + webdriver_frame_id: WebDriverFrameId, + reply: IpcSender<Result<BrowsingContextId, ()>>, +) { let result = match webdriver_frame_id { WebDriverFrameId::Short(_) => { // This isn't supported yet Err(()) }, - WebDriverFrameId::Element(x) => { - find_node_by_unique_id(documents, pipeline, x) - .and_then(|node| node.downcast::<HTMLIFrameElement>().and_then(|elem| elem.browsing_context_id())) - .ok_or(()) - }, - WebDriverFrameId::Parent => { - documents.find_window(pipeline) - .and_then(|window| window.window_proxy().parent().map(|parent| parent.browsing_context_id())) - .ok_or(()) - } + WebDriverFrameId::Element(x) => find_node_by_unique_id(documents, pipeline, x) + .and_then(|node| { + node.downcast::<HTMLIFrameElement>() + .and_then(|elem| elem.browsing_context_id()) + }).ok_or(()), + WebDriverFrameId::Parent => documents + .find_window(pipeline) + .and_then(|window| { + window + .window_proxy() + .parent() + .map(|parent| parent.browsing_context_id()) + }).ok_or(()), }; reply.send(result).unwrap() } -pub fn handle_find_element_css(documents: &Documents, pipeline: PipelineId, selector: String, - reply: IpcSender<Result<Option<String>, ()>>) { - let node_id = documents.find_document(pipeline) +pub fn handle_find_element_css( + documents: &Documents, + pipeline: PipelineId, + selector: String, + reply: IpcSender<Result<Option<String>, ()>>, +) { + let node_id = documents + .find_document(pipeline) .ok_or(()) .and_then(|doc| doc.QuerySelector(DOMString::from(selector)).map_err(|_| ())) .map(|node| node.map(|x| x.upcast::<Node>().unique_id())); reply.send(node_id).unwrap(); } -pub fn handle_find_elements_css(documents: &Documents, - pipeline: PipelineId, - selector: String, - reply: IpcSender<Result<Vec<String>, ()>>) { - let node_ids = documents.find_document(pipeline) +pub fn handle_find_elements_css( + documents: &Documents, + pipeline: PipelineId, + selector: String, + reply: IpcSender<Result<Vec<String>, ()>>, +) { + let node_ids = documents + .find_document(pipeline) .ok_or(()) - .and_then(|doc| doc.QuerySelectorAll(DOMString::from(selector)).map_err(|_| ())) - .map(|nodes| nodes.iter().map(|x| x.upcast::<Node>().unique_id()).collect()); + .and_then(|doc| { + doc.QuerySelectorAll(DOMString::from(selector)) + .map_err(|_| ()) + }).map(|nodes| { + nodes + .iter() + .map(|x| x.upcast::<Node>().unique_id()) + .collect() + }); reply.send(node_ids).unwrap(); } -pub fn handle_focus_element(documents: &Documents, - pipeline: PipelineId, - element_id: String, - reply: IpcSender<Result<(), ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, element_id) { - Some(ref node) => { - match node.downcast::<HTMLElement>() { - Some(ref elem) => { - // Need a way to find if this actually succeeded - elem.Focus(); - Ok(()) - } - None => Err(()) - } - }, - None => Err(()) - }).unwrap(); +pub fn handle_focus_element( + documents: &Documents, + pipeline: PipelineId, + element_id: String, + reply: IpcSender<Result<(), ()>>, +) { + reply + .send( + match find_node_by_unique_id(documents, pipeline, element_id) { + Some(ref node) => { + match node.downcast::<HTMLElement>() { + Some(ref elem) => { + // Need a way to find if this actually succeeded + elem.Focus(); + Ok(()) + }, + None => Err(()), + } + }, + None => Err(()), + }, + ).unwrap(); } -pub fn handle_get_active_element(documents: &Documents, - pipeline: PipelineId, - reply: IpcSender<Option<String>>) { - reply.send(documents.find_document(pipeline) - .and_then(|doc| doc.GetActiveElement()) - .map(|elem| elem.upcast::<Node>().unique_id())).unwrap(); +pub fn handle_get_active_element( + documents: &Documents, + pipeline: PipelineId, + reply: IpcSender<Option<String>>, +) { + reply + .send( + documents + .find_document(pipeline) + .and_then(|doc| doc.GetActiveElement()) + .map(|elem| elem.upcast::<Node>().unique_id()), + ).unwrap(); } -pub fn handle_get_cookies(documents: &Documents, - pipeline: PipelineId, - reply: IpcSender<Vec<Serde<Cookie<'static>>>>) { +pub fn handle_get_cookies( + documents: &Documents, + pipeline: PipelineId, + reply: IpcSender<Vec<Serde<Cookie<'static>>>>, +) { // TODO: Return an error if the pipeline doesn't exist? let cookies = match documents.find_document(pipeline) { None => Vec::new(), Some(document) => { let url = document.url(); let (sender, receiver) = ipc::channel().unwrap(); - let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - GetCookiesDataForUrl(url, sender, NonHTTP) - ); + let _ = document + .window() + .upcast::<GlobalScope>() + .resource_threads() + .send(GetCookiesDataForUrl(url, sender, NonHTTP)); receiver.recv().unwrap() }, }; @@ -199,206 +257,244 @@ pub fn handle_get_cookies(documents: &Documents, } // https://w3c.github.io/webdriver/webdriver-spec.html#get-cookie -pub fn handle_get_cookie(documents: &Documents, - pipeline: PipelineId, - name: String, - reply: IpcSender<Vec<Serde<Cookie<'static>>>>) { +pub fn handle_get_cookie( + documents: &Documents, + pipeline: PipelineId, + name: String, + reply: IpcSender<Vec<Serde<Cookie<'static>>>>, +) { // TODO: Return an error if the pipeline doesn't exist? let cookies = match documents.find_document(pipeline) { None => Vec::new(), Some(document) => { let url = document.url(); let (sender, receiver) = ipc::channel().unwrap(); - let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - GetCookiesDataForUrl(url, sender, NonHTTP) - ); + let _ = document + .window() + .upcast::<GlobalScope>() + .resource_threads() + .send(GetCookiesDataForUrl(url, sender, NonHTTP)); receiver.recv().unwrap() }, }; - reply.send(cookies.into_iter().filter(|c| c.name() == &*name).collect()).unwrap(); + reply + .send(cookies.into_iter().filter(|c| c.name() == &*name).collect()) + .unwrap(); } // https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie -pub fn handle_add_cookie(documents: &Documents, - pipeline: PipelineId, - cookie: Cookie<'static>, - reply: IpcSender<Result<(), WebDriverCookieError>>) { +pub fn handle_add_cookie( + documents: &Documents, + pipeline: PipelineId, + cookie: Cookie<'static>, + reply: IpcSender<Result<(), WebDriverCookieError>>, +) { // TODO: Return a different error if the pipeline doesn't exist? let document = match documents.find_document(pipeline) { Some(document) => document, - None => return reply.send(Err(WebDriverCookieError::UnableToSetCookie)).unwrap(), + None => { + return reply + .send(Err(WebDriverCookieError::UnableToSetCookie)) + .unwrap() + }, }; let url = document.url(); - let method = if cookie.http_only() { - HTTP - } else { - NonHTTP - }; + let method = if cookie.http_only() { HTTP } else { NonHTTP }; let domain = cookie.domain().map(ToOwned::to_owned); - reply.send(match (document.is_cookie_averse(), domain) { - (true, _) => Err(WebDriverCookieError::InvalidDomain), - (false, Some(ref domain)) if url.host_str().map(|x| { x == domain }).unwrap_or(false) => { - let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - SetCookieForUrl(url, Serde(cookie), method) - ); - Ok(()) - }, - (false, None) => { - let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - SetCookieForUrl(url, Serde(cookie), method) - ); - Ok(()) - }, - (_, _) => { - Err(WebDriverCookieError::UnableToSetCookie) - }, - }).unwrap(); + reply + .send(match (document.is_cookie_averse(), domain) { + (true, _) => Err(WebDriverCookieError::InvalidDomain), + (false, Some(ref domain)) if url.host_str().map(|x| x == domain).unwrap_or(false) => { + let _ = document + .window() + .upcast::<GlobalScope>() + .resource_threads() + .send(SetCookieForUrl(url, Serde(cookie), method)); + Ok(()) + }, + (false, None) => { + let _ = document + .window() + .upcast::<GlobalScope>() + .resource_threads() + .send(SetCookieForUrl(url, Serde(cookie), method)); + Ok(()) + }, + (_, _) => Err(WebDriverCookieError::UnableToSetCookie), + }).unwrap(); } pub fn handle_get_title(documents: &Documents, pipeline: PipelineId, reply: IpcSender<String>) { // TODO: Return an error if the pipeline doesn't exist. - let title = documents.find_document(pipeline) + let title = documents + .find_document(pipeline) .map(|doc| String::from(doc.Title())) .unwrap_or_default(); reply.send(title).unwrap(); } -pub fn handle_get_rect(documents: &Documents, - pipeline: PipelineId, - element_id: String, - reply: IpcSender<Result<Rect<f64>, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, element_id) { - Some(elem) => { - // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position - match elem.downcast::<HTMLElement>() { - Some(html_elem) => { - // Step 1 - let mut x = 0; - let mut y = 0; +pub fn handle_get_rect( + documents: &Documents, + pipeline: PipelineId, + element_id: String, + reply: IpcSender<Result<Rect<f64>, ()>>, +) { + reply + .send( + match find_node_by_unique_id(documents, pipeline, element_id) { + Some(elem) => { + // https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position + match elem.downcast::<HTMLElement>() { + Some(html_elem) => { + // Step 1 + let mut x = 0; + let mut y = 0; - let mut offset_parent = html_elem.GetOffsetParent(); + let mut offset_parent = html_elem.GetOffsetParent(); - // Step 2 - while let Some(element) = offset_parent { - offset_parent = match element.downcast::<HTMLElement>() { - Some(elem) => { - x += elem.OffsetLeft(); - y += elem.OffsetTop(); - elem.GetOffsetParent() - }, - None => None - }; + // Step 2 + while let Some(element) = offset_parent { + offset_parent = match element.downcast::<HTMLElement>() { + Some(elem) => { + x += elem.OffsetLeft(); + y += elem.OffsetTop(); + elem.GetOffsetParent() + }, + None => None, + }; + } + // Step 3 + Ok(Rect::new( + Point2D::new(x as f64, y as f64), + Size2D::new( + html_elem.OffsetWidth() as f64, + html_elem.OffsetHeight() as f64, + ), + )) + }, + None => Err(()), } - // Step 3 - Ok(Rect::new(Point2D::new(x as f64, y as f64), - Size2D::new(html_elem.OffsetWidth() as f64, - html_elem.OffsetHeight() as f64))) }, - None => Err(()) - } - }, - None => Err(()) - }).unwrap(); + None => Err(()), + }, + ).unwrap(); } -pub fn handle_get_text(documents: &Documents, - pipeline: PipelineId, - node_id: String, - reply: IpcSender<Result<String, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, node_id) { - Some(ref node) => { - Ok(node.GetTextContent().map_or("".to_owned(), String::from)) - }, - None => Err(()) - }).unwrap(); +pub fn handle_get_text( + documents: &Documents, + pipeline: PipelineId, + node_id: String, + reply: IpcSender<Result<String, ()>>, +) { + reply + .send(match find_node_by_unique_id(documents, pipeline, node_id) { + Some(ref node) => Ok(node.GetTextContent().map_or("".to_owned(), String::from)), + None => Err(()), + }).unwrap(); } -pub fn handle_get_name(documents: &Documents, - pipeline: PipelineId, - node_id: String, - reply: IpcSender<Result<String, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, node_id) { - Some(node) => { - Ok(String::from(node.downcast::<Element>().unwrap().TagName())) - }, - None => Err(()) - }).unwrap(); +pub fn handle_get_name( + documents: &Documents, + pipeline: PipelineId, + node_id: String, + reply: IpcSender<Result<String, ()>>, +) { + reply + .send(match find_node_by_unique_id(documents, pipeline, node_id) { + Some(node) => Ok(String::from(node.downcast::<Element>().unwrap().TagName())), + None => Err(()), + }).unwrap(); } -pub fn handle_get_attribute(documents: &Documents, - pipeline: PipelineId, - node_id: String, - name: String, - reply: IpcSender<Result<Option<String>, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, node_id) { - Some(node) => { - Ok(node.downcast::<Element>().unwrap().GetAttribute(DOMString::from(name)) - .map(String::from)) - }, - None => Err(()) - }).unwrap(); +pub fn handle_get_attribute( + documents: &Documents, + pipeline: PipelineId, + node_id: String, + name: String, + reply: IpcSender<Result<Option<String>, ()>>, +) { + reply + .send(match find_node_by_unique_id(documents, pipeline, node_id) { + Some(node) => Ok(node + .downcast::<Element>() + .unwrap() + .GetAttribute(DOMString::from(name)) + .map(String::from)), + None => Err(()), + }).unwrap(); } -pub fn handle_get_css(documents: &Documents, - pipeline: PipelineId, - node_id: String, - name: String, - reply: IpcSender<Result<String, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, node_id) { - Some(node) => { - let window = window_from_node(&*node); - let elem = node.downcast::<Element>().unwrap(); - Ok(String::from( - window.GetComputedStyle(&elem, None).GetPropertyValue(DOMString::from(name)))) - }, - None => Err(()) - }).unwrap(); +pub fn handle_get_css( + documents: &Documents, + pipeline: PipelineId, + node_id: String, + name: String, + reply: IpcSender<Result<String, ()>>, +) { + reply + .send(match find_node_by_unique_id(documents, pipeline, node_id) { + Some(node) => { + let window = window_from_node(&*node); + let elem = node.downcast::<Element>().unwrap(); + Ok(String::from( + window + .GetComputedStyle(&elem, None) + .GetPropertyValue(DOMString::from(name)), + )) + }, + None => Err(()), + }).unwrap(); } -pub fn handle_get_url(documents: &Documents, - pipeline: PipelineId, - reply: IpcSender<ServoUrl>) { +pub fn handle_get_url(documents: &Documents, pipeline: PipelineId, reply: IpcSender<ServoUrl>) { // TODO: Return an error if the pipeline doesn't exist. - let url = documents.find_document(pipeline) + let url = documents + .find_document(pipeline) .map(|document| document.url()) .unwrap_or_else(|| ServoUrl::parse("about:blank").expect("infallible")); reply.send(url).unwrap(); } -pub fn handle_is_enabled(documents: &Documents, - pipeline: PipelineId, - element_id: String, - reply: IpcSender<Result<bool, ()>>) { - reply.send(match find_node_by_unique_id(&documents, pipeline, element_id) { - Some(ref node) => { - match node.downcast::<Element>() { - Some(elem) => Ok(elem.enabled_state()), - None => Err(()) - } - }, - None => Err(()) - }).unwrap(); +pub fn handle_is_enabled( + documents: &Documents, + pipeline: PipelineId, + element_id: String, + reply: IpcSender<Result<bool, ()>>, +) { + reply + .send( + match find_node_by_unique_id(&documents, pipeline, element_id) { + Some(ref node) => match node.downcast::<Element>() { + Some(elem) => Ok(elem.enabled_state()), + None => Err(()), + }, + None => Err(()), + }, + ).unwrap(); } -pub fn handle_is_selected(documents: &Documents, - pipeline: PipelineId, - element_id: String, - reply: IpcSender<Result<bool, ()>>) { - reply.send(match find_node_by_unique_id(documents, pipeline, element_id) { - Some(ref node) => { - if let Some(input_element) = node.downcast::<HTMLInputElement>() { - Ok(input_element.Checked()) - } - else if let Some(option_element) = node.downcast::<HTMLOptionElement>() { - Ok(option_element.Selected()) - } - else if node.is::<HTMLElement>() { - Ok(false) // regular elements are not selectable - } else { - Err(()) - } - }, - None => Err(()) - }).unwrap(); +pub fn handle_is_selected( + documents: &Documents, + pipeline: PipelineId, + element_id: String, + reply: IpcSender<Result<bool, ()>>, +) { + reply + .send( + match find_node_by_unique_id(documents, pipeline, element_id) { + Some(ref node) => { + if let Some(input_element) = node.downcast::<HTMLInputElement>() { + Ok(input_element.Checked()) + } else if let Some(option_element) = node.downcast::<HTMLOptionElement>() { + Ok(option_element.Selected()) + } else if node.is::<HTMLElement>() { + Ok(false) // regular elements are not selectable + } else { + Err(()) + } + }, + None => Err(()), + }, + ).unwrap(); } |