diff options
-rw-r--r-- | components/msg/webdriver_msg.rs | 2 | ||||
-rw-r--r-- | components/script/script_thread.rs | 2 | ||||
-rw-r--r-- | components/script/webdriver_handlers.rs | 41 | ||||
-rw-r--r-- | components/webdriver_server/lib.rs | 23 |
4 files changed, 67 insertions, 1 deletions
diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs index 94c4556b5f0..fb59de4a922 100644 --- a/components/msg/webdriver_msg.rs +++ b/components/msg/webdriver_msg.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use constellation_msg::{PipelineId, WindowSizeData}; +use euclid::rect::Rect; use ipc_channel::ipc::IpcSender; use rustc_serialize::json::{Json, ToJson}; use url::Url; @@ -17,6 +18,7 @@ pub enum WebDriverScriptCommand { GetActiveElement(IpcSender<Option<String>>), GetElementAttribute(String, String, IpcSender<Result<Option<String>, ()>>), GetElementCSS(String, String, IpcSender<Result<String, ()>>), + GetElementRect(String, IpcSender<Result<Rect<f64>, ()>>), GetElementTagName(String, IpcSender<Result<String, ()>>), GetElementText(String, IpcSender<Result<String, ()>>), GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>), diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 1f4a82ec02d..ddf32f85406 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1246,6 +1246,8 @@ impl ScriptThread { webdriver_handlers::handle_get_attribute(&page, pipeline_id, node_id, name, reply), WebDriverScriptCommand::GetElementCSS(node_id, name, reply) => webdriver_handlers::handle_get_css(&page, pipeline_id, node_id, name, reply), + WebDriverScriptCommand::GetElementRect(node_id, reply) => + webdriver_handlers::handle_get_rect(&page, pipeline_id, node_id, reply), WebDriverScriptCommand::GetElementText(node_id, reply) => webdriver_handlers::handle_get_text(&page, pipeline_id, node_id, reply), WebDriverScriptCommand::GetFrameId(frame_id, reply) => diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 0c9831bf3f6..1b1d92fc914 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -22,6 +22,9 @@ use dom::htmlinputelement::HTMLInputElement; use dom::htmloptionelement::HTMLOptionElement; use dom::node::Node; use dom::window::ScriptHelpers; +use euclid::point::Point2D; +use euclid::rect::Rect; +use euclid::size::Size2D; use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use js::jsapi::{HandleValue, RootedValue}; @@ -185,6 +188,44 @@ pub fn handle_get_title(page: &Rc<Page>, _pipeline: PipelineId, reply: IpcSender reply.send(String::from(page.document().Title())).unwrap(); } +pub fn handle_get_rect(page: &Rc<Page>, + pipeline: PipelineId, + element_id: String, + reply: IpcSender<Result<Rect<f64>, ()>>) { + reply.send(match find_node_by_unique_id(&*page, 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(); + + // 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(()) + } + }, + None => Err(()) + }).unwrap(); +} + pub fn handle_get_text(page: &Rc<Page>, pipeline: PipelineId, node_id: String, diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 2979609c295..aa1e6ae4135 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -51,7 +51,8 @@ use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverM use webdriver::common::{LocatorStrategy, WebElement}; use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult}; use webdriver::httpapi::{WebDriverExtensionRoute}; -use webdriver::response::{NewSessionResponse, ValueResponse, WebDriverResponse, WindowSizeResponse}; +use webdriver::response::{ElementRectResponse, NewSessionResponse, ValueResponse}; +use webdriver::response::{WebDriverResponse, WindowSizeResponse}; use webdriver::server::{self, Session, WebDriverHandler}; fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> { @@ -540,6 +541,25 @@ impl Handler { } } + // https://w3c.github.io/webdriver/webdriver-spec.html#get-element-rect + fn handle_element_rect(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> { + let pipeline_id = try!(self.frame_pipeline()); + + let (sender, receiver) = ipc::channel().unwrap(); + let cmd = WebDriverScriptCommand::GetElementRect(element.id.clone(), sender); + let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd); + self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap(); + match receiver.recv().unwrap() { + Ok(rect) => { + let response = ElementRectResponse::new(rect.origin.x, rect.origin.y, + rect.size.width, rect.size.height); + Ok(WebDriverResponse::ElementRect(response)) + }, + Err(_) => Err(WebDriverError::new(ErrorStatus::StaleElementReference, + "Unable to find element in document")) + } + } + fn handle_element_text(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> { let pipeline_id = try!(self.frame_pipeline()); @@ -798,6 +818,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler { WebDriverCommand::FindElement(ref parameters) => self.handle_find_element(parameters), WebDriverCommand::FindElements(ref parameters) => self.handle_find_elements(parameters), WebDriverCommand::GetActiveElement => self.handle_active_element(), + WebDriverCommand::GetElementRect(ref element) => self.handle_element_rect(element), WebDriverCommand::GetElementText(ref element) => self.handle_element_text(element), WebDriverCommand::GetElementTagName(ref element) => self.handle_element_tag_name(element), WebDriverCommand::GetElementAttribute(ref element, ref name) => |