mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Auto merge of #9708 - danlrobertson:i8623, r=KiChjang
Implement GetElementRect webdriver command: #8623 Implement the webdriver Get Element Rect command. Originally I wrote out the algorithm for [Step 7](https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position) and then I found `GetBoundingClientRect`, and i thought it was probably best to use it instead. As always, feedback is very welcomed! <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9708) <!-- Reviewable:end -->
This commit is contained in:
commit
e5f3c5b6d1
4 changed files with 68 additions and 10 deletions
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use constellation_msg::{PipelineId, WindowSizeData};
|
use constellation_msg::{PipelineId, WindowSizeData};
|
||||||
|
use euclid::rect::Rect;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use rustc_serialize::json::{Json, ToJson};
|
use rustc_serialize::json::{Json, ToJson};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -17,6 +18,7 @@ pub enum WebDriverScriptCommand {
|
||||||
GetActiveElement(IpcSender<Option<String>>),
|
GetActiveElement(IpcSender<Option<String>>),
|
||||||
GetElementAttribute(String, String, IpcSender<Result<Option<String>, ()>>),
|
GetElementAttribute(String, String, IpcSender<Result<Option<String>, ()>>),
|
||||||
GetElementCSS(String, String, IpcSender<Result<String, ()>>),
|
GetElementCSS(String, String, IpcSender<Result<String, ()>>),
|
||||||
|
GetElementRect(String, IpcSender<Result<Rect<f64>, ()>>),
|
||||||
GetElementTagName(String, IpcSender<Result<String, ()>>),
|
GetElementTagName(String, IpcSender<Result<String, ()>>),
|
||||||
GetElementText(String, IpcSender<Result<String, ()>>),
|
GetElementText(String, IpcSender<Result<String, ()>>),
|
||||||
GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>),
|
GetFrameId(WebDriverFrameId, IpcSender<Result<Option<PipelineId>, ()>>),
|
||||||
|
|
|
@ -1246,6 +1246,8 @@ impl ScriptThread {
|
||||||
webdriver_handlers::handle_get_attribute(&page, pipeline_id, node_id, name, reply),
|
webdriver_handlers::handle_get_attribute(&page, pipeline_id, node_id, name, reply),
|
||||||
WebDriverScriptCommand::GetElementCSS(node_id, name, reply) =>
|
WebDriverScriptCommand::GetElementCSS(node_id, name, reply) =>
|
||||||
webdriver_handlers::handle_get_css(&page, pipeline_id, 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) =>
|
WebDriverScriptCommand::GetElementText(node_id, reply) =>
|
||||||
webdriver_handlers::handle_get_text(&page, pipeline_id, node_id, reply),
|
webdriver_handlers::handle_get_text(&page, pipeline_id, node_id, reply),
|
||||||
WebDriverScriptCommand::GetFrameId(frame_id, reply) =>
|
WebDriverScriptCommand::GetFrameId(frame_id, reply) =>
|
||||||
|
|
|
@ -22,6 +22,9 @@ use dom::htmlinputelement::HTMLInputElement;
|
||||||
use dom::htmloptionelement::HTMLOptionElement;
|
use dom::htmloptionelement::HTMLOptionElement;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
use dom::window::ScriptHelpers;
|
use dom::window::ScriptHelpers;
|
||||||
|
use euclid::point::Point2D;
|
||||||
|
use euclid::rect::Rect;
|
||||||
|
use euclid::size::Size2D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use js::jsapi::JSContext;
|
use js::jsapi::JSContext;
|
||||||
use js::jsapi::{HandleValue, RootedValue};
|
use js::jsapi::{HandleValue, RootedValue};
|
||||||
|
@ -37,15 +40,7 @@ use util::str::DOMString;
|
||||||
fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Option<Root<Node>> {
|
fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Option<Root<Node>> {
|
||||||
let page = get_page(&*page, pipeline);
|
let page = get_page(&*page, pipeline);
|
||||||
let document = page.document();
|
let document = page.document();
|
||||||
let node = document.upcast::<Node>();
|
document.upcast::<Node>().traverse_preorder().find(|candidate| candidate.get_unique_id() == node_id)
|
||||||
|
|
||||||
for candidate in node.traverse_preorder() {
|
|
||||||
if candidate.get_unique_id() == node_id {
|
|
||||||
return Some(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -185,6 +180,44 @@ pub fn handle_get_title(page: &Rc<Page>, _pipeline: PipelineId, reply: IpcSender
|
||||||
reply.send(String::from(page.document().Title())).unwrap();
|
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>,
|
pub fn handle_get_text(page: &Rc<Page>,
|
||||||
pipeline: PipelineId,
|
pipeline: PipelineId,
|
||||||
node_id: String,
|
node_id: String,
|
||||||
|
|
|
@ -51,7 +51,8 @@ use webdriver::command::{WebDriverCommand, WebDriverExtensionCommand, WebDriverM
|
||||||
use webdriver::common::{LocatorStrategy, WebElement};
|
use webdriver::common::{LocatorStrategy, WebElement};
|
||||||
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
||||||
use webdriver::httpapi::{WebDriverExtensionRoute};
|
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};
|
use webdriver::server::{self, Session, WebDriverHandler};
|
||||||
|
|
||||||
fn extension_routes() -> Vec<(Method, &'static str, ServoExtensionRoute)> {
|
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> {
|
fn handle_element_text(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
||||||
let pipeline_id = try!(self.frame_pipeline());
|
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::FindElement(ref parameters) => self.handle_find_element(parameters),
|
||||||
WebDriverCommand::FindElements(ref parameters) => self.handle_find_elements(parameters),
|
WebDriverCommand::FindElements(ref parameters) => self.handle_find_elements(parameters),
|
||||||
WebDriverCommand::GetActiveElement => self.handle_active_element(),
|
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::GetElementText(ref element) => self.handle_element_text(element),
|
||||||
WebDriverCommand::GetElementTagName(ref element) => self.handle_element_tag_name(element),
|
WebDriverCommand::GetElementTagName(ref element) => self.handle_element_tag_name(element),
|
||||||
WebDriverCommand::GetElementAttribute(ref element, ref name) =>
|
WebDriverCommand::GetElementAttribute(ref element, ref name) =>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue