servo: Merge #6009 - Add support for switching frames with the webdriver API (from jgraham:webdriver_frames); r=jdm

This moves webdriver_traits into msg to avoid a circular dependency.

Source-Repo: https://github.com/servo/servo
Source-Revision: d08995e1a94fa093b7fc1e5d918d9dca79f260d6
This commit is contained in:
James Graham 2015-06-01 17:30:37 -05:00
parent 6ed17c03e5
commit 35d7b3b717
20 changed files with 273 additions and 122 deletions

View File

@ -37,9 +37,6 @@ path = "../style"
[dependencies.util]
path = "../util"
[dependencies.webdriver_traits]
path = "../webdriver_traits"
[dependencies.devtools_traits]
path = "../devtools_traits"

View File

@ -29,7 +29,8 @@ use msg::constellation_msg::{IFrameSandboxState, MozBrowserEvent, NavigationDire
use msg::constellation_msg::{Key, KeyState, KeyModifiers, LoadData};
use msg::constellation_msg::{SubpageId, WindowSizeData};
use msg::constellation_msg::{self, ConstellationChan, Failure};
use msg::constellation_msg::{WebDriverCommandMsg};
use msg::constellation_msg::WebDriverCommandMsg;
use msg::webdriver_msg;
use net_traits::{self, ResourceTask};
use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::{StorageTask, StorageTaskMsg};
@ -50,7 +51,6 @@ use util::geometry::PagePx;
use util::opts;
use util::task::spawn_named;
use clipboard::ClipboardContext;
use webdriver_traits;
/// Maintains the pipelines and navigation context and grants permission to composite.
///
@ -190,7 +190,7 @@ pub struct SendableFrameTree {
}
struct WebDriverData {
load_channel: Option<Sender<webdriver_traits::LoadComplete>>
load_channel: Option<Sender<webdriver_msg::LoadComplete>>
}
impl WebDriverData {
@ -425,9 +425,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
subpage_id,
event);
}
ConstellationMsg::GetRootPipeline(resp_chan) => {
ConstellationMsg::GetPipeline(frame_id, resp_chan) => {
debug!("constellation got get root pipeline message");
self.handle_get_root_pipeline(resp_chan);
self.handle_get_pipeline(frame_id, resp_chan);
}
ConstellationMsg::GetFrame(parent_pipeline_id, subpage_id, resp_chan) => {
debug!("constellation got get root pipeline message");
self.handle_get_frame(parent_pipeline_id, subpage_id, resp_chan);
}
ConstellationMsg::Focus(pipeline_id) => {
debug!("constellation got focus message");
@ -691,7 +695,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
let back = !self.mut_frame(frame_id).prev.is_empty();
self.compositor_proxy.send(CompositorMsg::LoadComplete(back, forward));
if let Some(ref reply_chan) = self.webdriver.load_channel {
reply_chan.send(webdriver_traits::LoadComplete).unwrap();
reply_chan.send(webdriver_msg::LoadComplete).unwrap();
}
self.webdriver.load_channel = None;
}
@ -815,14 +819,24 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pipeline.trigger_mozbrowser_event(subpage_id, event);
}
fn handle_get_root_pipeline(&mut self, resp_chan: Sender<Option<PipelineId>>) {
let pipeline_id = self.root_frame_id.map(|frame_id| {
fn handle_get_pipeline(&mut self, frame_id: Option<FrameId>,
resp_chan: Sender<Option<PipelineId>>) {
let pipeline_id = frame_id.or(self.root_frame_id).map(|frame_id| {
let frame = self.frames.get(&frame_id).unwrap();
frame.current
});
resp_chan.send(pipeline_id).unwrap();
}
fn handle_get_frame(&mut self,
containing_pipeline_id: PipelineId,
subpage_id: SubpageId,
resp_chan: Sender<Option<FrameId>>) {
let frame_id = self.subpage_map.get(&(containing_pipeline_id, subpage_id)).and_then(
|x| self.pipeline_to_frame_map.get(&x)).map(|x| *x);
resp_chan.send(frame_id).unwrap();
}
fn focus_parent_pipeline(&self, pipeline_id: PipelineId) {
// Send a message to the parent of the provided pipeline (if it exists)
// telling it to mark the iframe element as focused.

View File

@ -28,7 +28,6 @@ extern crate style;
#[macro_use]
extern crate util;
extern crate gleam;
extern crate webdriver_traits;
extern crate clipboard;
extern crate libc;

View File

@ -13,9 +13,6 @@ path = "../style"
[dependencies.util]
path = "../util"
[dependencies.webdriver_traits]
path = "../webdriver_traits"
[dependencies.azure]
git = "https://github.com/servo/rust-azure"
@ -38,3 +35,4 @@ git = "https://github.com/servo/rust-png"
url = "0.2.16"
bitflags = "*"
hyper = "0.4"
rustc-serialize = "0.3.4"

View File

@ -18,8 +18,8 @@ use util::geometry::{PagePx, ViewportPx};
use std::collections::HashMap;
use std::sync::mpsc::{channel, Sender, Receiver};
use style::viewport::ViewportConstraints;
use webdriver_traits::{WebDriverScriptCommand, LoadComplete};
use url::Url;
use webdriver_msg::{WebDriverScriptCommand, LoadComplete};
#[derive(Clone)]
pub struct ConstellationChan(pub Sender<Msg>);
@ -230,8 +230,12 @@ pub enum Msg {
ChangeRunningAnimationsState(PipelineId, AnimationState),
/// Requests that the constellation instruct layout to begin a new tick of the animation.
TickAnimation(PipelineId),
/// Request that the constellation send the current root pipeline id over a provided channel
GetRootPipeline(Sender<Option<PipelineId>>),
/// Request that the constellation send the current pipeline id for the provided frame
/// id, or for the root frame if this is None, over a provided channel
GetPipeline(Option<FrameId>, Sender<Option<PipelineId>>),
/// Request that the constellation send the FrameId corresponding to the document
/// with the provided parent pipeline id and subpage id
GetFrame(PipelineId, SubpageId, Sender<Option<FrameId>>),
/// Notifies the constellation that this frame has received focus.
Focus(PipelineId),
/// Requests that the constellation retrieve the current contents of the clipboard

View File

@ -8,10 +8,10 @@ extern crate geom;
extern crate hyper;
extern crate layers;
extern crate png;
extern crate rustc_serialize;
extern crate util;
extern crate url;
extern crate style;
extern crate webdriver_traits;
#[cfg(target_os="macos")]
extern crate core_foundation;
@ -20,3 +20,4 @@ extern crate io_surface;
pub mod compositor_msg;
pub mod constellation_msg;
pub mod webdriver_msg;

View File

@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use rustc_serialize::json::{Json, ToJson};
use constellation_msg::{PipelineId, SubpageId};
use std::sync::mpsc::Sender;
pub enum WebDriverScriptCommand {
ExecuteScript(String, Sender<WebDriverJSResult>),
ExecuteAsyncScript(String, Sender<WebDriverJSResult>),
FindElementCSS(String, Sender<Result<Option<String>, ()>>),
FindElementsCSS(String, Sender<Result<Vec<String>, ()>>),
GetActiveElement(Sender<Option<String>>),
GetElementTagName(String, Sender<Result<String, ()>>),
GetElementText(String, Sender<Result<String, ()>>),
GetFrameId(WebDriverFrameId, Sender<Result<Option<(PipelineId, SubpageId)>, ()>>),
GetTitle(Sender<String>)
}
pub enum WebDriverJSValue {
Undefined,
Null,
Boolean(bool),
Number(f64),
String(String),
// TODO: Object and WebElement
}
pub enum WebDriverJSError {
Timeout,
UnknownType
}
pub type WebDriverJSResult = Result<WebDriverJSValue, WebDriverJSError>;
pub enum WebDriverFrameId {
Short(u16),
Element(String),
Parent
}
impl ToJson for WebDriverJSValue {
fn to_json(&self) -> Json {
match *self {
WebDriverJSValue::Undefined => Json::Null,
WebDriverJSValue::Null => Json::Null,
WebDriverJSValue::Boolean(ref x) => x.to_json(),
WebDriverJSValue::Number(ref x) => x.to_json(),
WebDriverJSValue::String(ref x) => x.to_json()
}
}
}
pub struct LoadComplete;

View File

@ -45,9 +45,6 @@ path = "../canvas"
[dependencies.canvas_traits]
path = "../canvas_traits"
[dependencies.webdriver_traits]
path = "../webdriver_traits"
[dependencies.selectors]
git = "https://github.com/servo/rust-selectors"

View File

@ -38,9 +38,9 @@ use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use webdriver_handlers::jsval_to_webdriver;
use devtools_traits::{DevtoolsControlChan, TimelineMarker, TimelineMarkerType, TracingMetadata};
use webdriver_traits::{WebDriverJSError, WebDriverJSResult};
use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId};
use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use net_traits::ResourceTask;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask};
use net_traits::storage_task::{StorageTask, StorageType};
@ -437,17 +437,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
// https://html.spec.whatwg.org/multipage/#dom-parent
fn Parent(self) -> Temporary<Window> {
let browser_context = self.browser_context();
let browser_context = browser_context.as_ref().unwrap();
browser_context.frame_element().map_or(self.Window(), |fe| {
let frame_element = fe.root();
let window = window_from_node(frame_element.r()).root();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let r = window.r();
let context = r.browser_context();
context.as_ref().unwrap().active_window()
})
self.parent().unwrap_or(self.Window())
}
fn Performance(self) -> Temporary<Performance> {
@ -558,6 +548,7 @@ pub trait WindowHelpers {
fn drop_devtools_timeline_markers(self);
fn set_webdriver_script_chan(self, chan: Option<Sender<WebDriverJSResult>>);
fn is_alive(self) -> bool;
fn parent(self) -> Option<Temporary<Window>>;
}
pub trait ScriptHelpers {
@ -939,6 +930,20 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
fn is_alive(self) -> bool {
self.current_state.get() == WindowState::Alive
}
fn parent(self) -> Option<Temporary<Window>> {
let browser_context = self.browser_context();
let browser_context = browser_context.as_ref().unwrap();
browser_context.frame_element().map(|fe| {
let frame_element = fe.root();
let window = window_from_node(frame_element.r()).root();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let r = window.r();
let context = r.browser_context();
context.as_ref().unwrap().active_window()
})
}
}
impl Window {

View File

@ -52,7 +52,6 @@ extern crate unicase;
extern crate url;
extern crate uuid;
extern crate string_cache;
extern crate webdriver_traits;
extern crate offscreen_gl_context;
pub mod cors;

View File

@ -62,12 +62,12 @@ use script_traits::CompositorEvent::{MouseMoveEvent, KeyEvent};
use script_traits::{NewLayoutInfo, OpaqueScriptLayoutChannel};
use script_traits::{ConstellationControlMsg, ScriptControlChan};
use script_traits::{ScriptState, ScriptTaskFactory};
use webdriver_traits::WebDriverScriptCommand;
use msg::compositor_msg::{LayerId, ScriptListener};
use msg::constellation_msg::{ConstellationChan, FocusType};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::webdriver_msg::WebDriverScriptCommand;
use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata};
use net_traits::LoadData as NetLoadData;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
@ -835,6 +835,8 @@ impl ScriptTask {
webdriver_handlers::handle_get_name(&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) =>
webdriver_handlers::handle_get_frame_id(&page, pipeline_id, frame_id, reply),
WebDriverScriptCommand::GetTitle(reply) =>
webdriver_handlers::handle_get_title(&page, pipeline_id, reply),
WebDriverScriptCommand::ExecuteAsyncScript(script, reply) =>

View File

@ -2,12 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use webdriver_traits::{WebDriverJSValue, WebDriverJSError, WebDriverJSResult};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLIFrameElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::js::{OptionalRootable, Rootable, Temporary};
@ -17,7 +17,8 @@ use dom::document::DocumentHelpers;
use js::jsapi::JSContext;
use js::jsval::JSVal;
use page::Page;
use msg::constellation_msg::PipelineId;
use msg::constellation_msg::{PipelineId, SubpageId};
use msg::webdriver_msg::{WebDriverJSValue, WebDriverJSError, WebDriverJSResult, WebDriverFrameId};
use script_task::get_page;
use std::rc::Rc;
@ -73,6 +74,36 @@ pub fn handle_execute_async_script(page: &Rc<Page>, pipeline: PipelineId, eval:
window.r().evaluate_js_on_global_with_result(&eval);
}
pub fn handle_get_frame_id(page: &Rc<Page>,
pipeline: PipelineId,
webdriver_frame_id: WebDriverFrameId,
reply: Sender<Result<Option<(PipelineId, SubpageId)>, ()>>) {
let window = match webdriver_frame_id {
WebDriverFrameId::Short(_) => {
// This isn't supported yet
Ok(None)
},
WebDriverFrameId::Element(x) => {
match find_node_by_unique_id(page, pipeline, x) {
Some(ref node) => {
match HTMLIFrameElementCast::to_ref(node.root().r()) {
Some(ref elem) => Ok(elem.GetContentWindow()),
None => Err(())
}
},
None => Err(())
}
},
WebDriverFrameId::Parent => {
let window = page.window();
Ok(window.root().r().parent())
}
};
let frame_id = window.map(|x| x.and_then(|x| x.root().r().parent_info()));
reply.send(frame_id).unwrap()
}
pub fn handle_find_element_css(page: &Rc<Page>, _pipeline: PipelineId, selector: String,
reply: Sender<Result<Option<String>, ()>>) {
reply.send(match page.document().root().r().QuerySelector(selector.clone()) {

View File

@ -19,9 +19,6 @@ path = "../util"
[dependencies.devtools_traits]
path = "../devtools_traits"
[dependencies.webdriver_traits]
path = "../webdriver_traits"
[dependencies.geom]
git = "https://github.com/servo/rust-geom"

View File

@ -15,7 +15,6 @@ extern crate msg;
extern crate net_traits;
extern crate util;
extern crate url;
extern crate webdriver_traits;
use devtools_traits::DevtoolsControlChan;
use libc::c_void;
@ -23,12 +22,12 @@ use msg::constellation_msg::{ConstellationChan, PipelineId, Failure, WindowSizeD
use msg::constellation_msg::{LoadData, SubpageId, Key, KeyState, KeyModifiers};
use msg::constellation_msg::{MozBrowserEvent, PipelineExitType};
use msg::compositor_msg::ScriptListener;
use msg::webdriver_msg::WebDriverScriptCommand;
use net_traits::ResourceTask;
use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::StorageTask;
use std::any::Any;
use std::sync::mpsc::{Sender, Receiver};
use webdriver_traits::WebDriverScriptCommand;
use url::Url;
use geom::point::Point2D;

View File

@ -146,7 +146,6 @@ dependencies = [
"time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -786,10 +785,10 @@ dependencies = [
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"png 0.1.0 (git+https://github.com/servo/rust-png)",
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -1071,7 +1070,6 @@ dependencies = [
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver_traits 0.0.1",
"websocket 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1094,7 +1092,6 @@ dependencies = [
"net_traits 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -1337,14 +1334,6 @@ dependencies = [
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.2.0 (git+https://github.com/jgraham/webdriver-rust.git)",
"webdriver_traits 0.0.1",
]
[[package]]
name = "webdriver_traits"
version = "0.0.1"
dependencies = [
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

View File

@ -13,9 +13,6 @@ path = "../msg"
[dependencies.util]
path = "../util"
[dependencies.webdriver_traits]
path = "../webdriver_traits"
[dependencies.webdriver]
git = "https://github.com/jgraham/webdriver-rust.git"

View File

@ -17,16 +17,17 @@ extern crate url;
extern crate util;
extern crate rustc_serialize;
extern crate uuid;
extern crate webdriver_traits;
use msg::constellation_msg::{ConstellationChan, LoadData, PipelineId, NavigationDirection, WebDriverCommandMsg};
use msg::constellation_msg::{ConstellationChan, LoadData, FrameId, PipelineId, NavigationDirection,
WebDriverCommandMsg};
use msg::constellation_msg::Msg as ConstellationMsg;
use std::sync::mpsc::{channel, Receiver};
use webdriver_traits::{WebDriverScriptCommand, WebDriverJSError, WebDriverJSResult};
use msg::webdriver_msg::{WebDriverFrameId, WebDriverScriptCommand, WebDriverJSError, WebDriverJSResult};
use url::Url;
use webdriver::command::{WebDriverMessage, WebDriverCommand};
use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters, TimeoutsParameters};
use webdriver::command::{GetParameters, JavascriptCommandParameters, LocatorParameters,
SwitchToFrameParameters, TimeoutsParameters};
use webdriver::common::{LocatorStrategy, WebElement};
use webdriver::response::{
WebDriverResponse, NewSessionResponse, ValueResponse};
@ -51,22 +52,24 @@ pub fn start_server(port: u16, constellation_chan: ConstellationChan) {
});
}
struct WebdriverSession {
id: Uuid
struct WebDriverSession {
id: Uuid,
frame_id: Option<FrameId>
}
struct Handler {
session: Option<WebdriverSession>,
session: Option<WebDriverSession>,
constellation_chan: ConstellationChan,
script_timeout: u32,
load_timeout: u32,
implicit_wait_timeout: u32
}
impl WebdriverSession {
pub fn new() -> WebdriverSession {
WebdriverSession {
id: Uuid::new_v4()
impl WebDriverSession {
pub fn new() -> WebDriverSession {
WebDriverSession {
id: Uuid::new_v4(),
frame_id: None
}
}
}
@ -87,25 +90,60 @@ impl Handler {
let iterations = 30_000 / interval;
for _ in 0..iterations {
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::GetRootPipeline(sender)).unwrap();
if let Some(x) = reciever.recv().unwrap() {
return Ok(x);
if let Some(x) = self.get_pipeline(None) {
return Ok(x)
};
sleep_ms(interval)
sleep_ms(interval);
};
Err(WebDriverError::new(ErrorStatus::Timeout,
"Failed to get root window handle"))
}
fn get_frame_pipeline(&self) -> WebDriverResult<PipelineId> {
if let Some(ref session) = self.session {
match self.get_pipeline(session.frame_id) {
Some(x) => Ok(x),
None => Err(WebDriverError::new(ErrorStatus::NoSuchFrame,
"Frame got closed"))
}
} else {
panic!("Command tried to access session but session is None");
}
}
fn get_session(&self) -> WebDriverResult<&WebDriverSession> {
match self.session {
Some(ref x) => Ok(x),
None => Err(WebDriverError::new(ErrorStatus::SessionNotCreated,
"Session not created"))
}
}
fn set_frame_id(&mut self, frame_id: Option<FrameId>) -> WebDriverResult<()> {
match self.session {
Some(ref mut x) => {
x.frame_id = frame_id;
Ok(())
},
None => Err(WebDriverError::new(ErrorStatus::SessionNotCreated,
"Session not created"))
}
}
fn get_pipeline(&self, frame_id: Option<FrameId>) -> Option<PipelineId> {
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::GetPipeline(frame_id, sender)).unwrap();
reciever.recv().unwrap()
}
fn handle_new_session(&mut self) -> WebDriverResult<WebDriverResponse> {
if self.session.is_none() {
let session = WebdriverSession::new();
let session = WebDriverSession::new();
let mut capabilities = BTreeMap::new();
capabilities.insert("browserName".to_owned(), "servo".to_json());
capabilities.insert("browserVersion".to_owned(), "0.0.1".to_json());
@ -182,7 +220,7 @@ impl Handler {
}
fn handle_find_element(&self, parameters: &LocatorParameters) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
if parameters.using != LocatorStrategy::CSSSelector {
return Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
@ -204,8 +242,60 @@ impl Handler {
}
}
fn handle_switch_to_frame(&mut self, parameters: &SwitchToFrameParameters) -> WebDriverResult<WebDriverResponse> {
use webdriver::common::FrameId;
let frame_id = match parameters.id {
FrameId::Null => {
self.set_frame_id(None).unwrap();
return Ok(WebDriverResponse::Void)
},
FrameId::Short(ref x) => WebDriverFrameId::Short(*x),
FrameId::Element(ref x) => WebDriverFrameId::Element(x.id.clone())
};
self.switch_to_frame(frame_id)
}
fn handle_switch_to_parent_frame(&mut self) -> WebDriverResult<WebDriverResponse> {
self.switch_to_frame(WebDriverFrameId::Parent)
}
fn switch_to_frame(&mut self, frame_id: WebDriverFrameId) -> WebDriverResult<WebDriverResponse> {
if let WebDriverFrameId::Short(_) = frame_id {
return Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
"Selecting frame by id not supported"));
}
let pipeline_id = try!(self.get_frame_pipeline());
let (sender, reciever) = channel();
let cmd = WebDriverScriptCommand::GetFrameId(frame_id, sender);
{
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::WebDriverCommand(
WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd))).unwrap();
}
let frame = match reciever.recv().unwrap() {
Ok(Some((pipeline_id, subpage_id))) => {
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
const_chan.send(ConstellationMsg::GetFrame(pipeline_id, subpage_id, sender)).unwrap();
reciever.recv().unwrap()
},
Ok(None) => None,
Err(_) => {
return Err(WebDriverError::new(ErrorStatus::NoSuchFrame,
"Frame does not exist"));
}
};
self.set_frame_id(frame).unwrap();
Ok(WebDriverResponse::Void)
}
fn handle_find_elements(&self, parameters: &LocatorParameters) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
if parameters.using != LocatorStrategy::CSSSelector {
return Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
@ -229,7 +319,7 @@ impl Handler {
}
fn handle_get_element_text(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
@ -244,7 +334,7 @@ impl Handler {
}
fn handle_get_active_element(&self) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
@ -256,7 +346,7 @@ impl Handler {
}
fn handle_get_element_tag_name(&self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
let (sender, reciever) = channel();
let ConstellationChan(ref const_chan) = self.constellation_chan;
@ -314,9 +404,7 @@ impl Handler {
fn execute_script(&self,
command: WebDriverScriptCommand,
reciever: Receiver<WebDriverJSResult>) -> WebDriverResult<WebDriverResponse> {
// TODO: This isn't really right because it always runs the script in the
// root window
let pipeline_id = try!(self.get_root_pipeline());
let pipeline_id = try!(self.get_frame_pipeline());
let ConstellationChan(ref const_chan) = self.constellation_chan;
let cmd_msg = WebDriverCommandMsg::ScriptCommand(pipeline_id, command);
@ -376,6 +464,15 @@ impl WebDriverHandler for Handler {
_session: &Option<Session>,
msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> {
// Unless we are trying to create a new session, we need to ensure that a
// session has previously been created
match msg.command {
WebDriverCommand::NewSession => {},
_ => {
try!(self.get_session());
}
}
match msg.command {
WebDriverCommand::NewSession => self.handle_new_session(),
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
@ -384,6 +481,8 @@ impl WebDriverHandler for Handler {
WebDriverCommand::GetTitle => self.handle_get_title(),
WebDriverCommand::GetWindowHandle => self.handle_get_window_handle(),
WebDriverCommand::GetWindowHandles => self.handle_get_window_handles(),
WebDriverCommand::SwitchToFrame(ref parameters) => self.handle_switch_to_frame(parameters),
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::GetActiveElement => self.handle_get_active_element(),

View File

@ -1,11 +0,0 @@
[package]
name = "webdriver_traits"
version = "0.0.1"
authors = ["The Servo Project Developers"]
[lib]
name = "webdriver_traits"
path = "lib.rs"
[dependencies]
rustc-serialize="0.3.4"

View File

@ -155,7 +155,6 @@ dependencies = [
"time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -788,10 +787,10 @@ dependencies = [
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"png 0.1.0 (git+https://github.com/servo/rust-png)",
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -1061,7 +1060,6 @@ dependencies = [
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver_traits 0.0.1",
"websocket 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1076,7 +1074,6 @@ dependencies = [
"net_traits 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -1322,14 +1319,6 @@ dependencies = [
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.2.0 (git+https://github.com/jgraham/webdriver-rust.git)",
"webdriver_traits 0.0.1",
]
[[package]]
name = "webdriver_traits"
version = "0.0.1"
dependencies = [
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

View File

@ -132,7 +132,6 @@ dependencies = [
"time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -687,10 +686,10 @@ dependencies = [
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"png 0.1.0 (git+https://github.com/servo/rust-png)",
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -942,7 +941,6 @@ dependencies = [
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver_traits 0.0.1",
"websocket 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -957,7 +955,6 @@ dependencies = [
"net_traits 0.0.1",
"url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webdriver_traits 0.0.1",
]
[[package]]
@ -1184,14 +1181,6 @@ dependencies = [
"util 0.0.1",
"uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.2.0 (git+https://github.com/jgraham/webdriver-rust.git)",
"webdriver_traits 0.0.1",
]
[[package]]
name = "webdriver_traits"
version = "0.0.1"
dependencies = [
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]