diff options
author | James Graham <james@hoppipolla.co.uk> | 2015-05-11 14:47:10 +0100 |
---|---|---|
committer | James Graham <james@hoppipolla.co.uk> | 2015-06-01 23:18:55 +0100 |
commit | 49f1b13ad968467e442d9bc7bc1ee737365e1f5d (patch) | |
tree | 6459e79dab04095889035a8aad9b7d933f294077 | |
parent | c724444ccb85551b5a0a581d673875ec9bce3d1f (diff) | |
download | servo-49f1b13ad968467e442d9bc7bc1ee737365e1f5d.tar.gz servo-49f1b13ad968467e442d9bc7bc1ee737365e1f5d.zip |
Add support for switching frames with the webdriver API.
This moves webdriver_traits into msg to avoid a circular dependency.
-rw-r--r-- | components/compositing/Cargo.toml | 3 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 30 | ||||
-rw-r--r-- | components/compositing/lib.rs | 1 | ||||
-rw-r--r-- | components/msg/Cargo.toml | 4 | ||||
-rw-r--r-- | components/msg/constellation_msg.rs | 10 | ||||
-rw-r--r-- | components/msg/lib.rs | 3 | ||||
-rw-r--r-- | components/msg/webdriver_msg.rs | 56 | ||||
-rw-r--r-- | components/script/Cargo.toml | 3 | ||||
-rw-r--r-- | components/script/dom/window.rs | 29 | ||||
-rw-r--r-- | components/script/lib.rs | 1 | ||||
-rw-r--r-- | components/script/script_task.rs | 4 | ||||
-rw-r--r-- | components/script/webdriver_handlers.rs | 37 | ||||
-rw-r--r-- | components/script_traits/Cargo.toml | 3 | ||||
-rw-r--r-- | components/script_traits/lib.rs | 3 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 13 | ||||
-rw-r--r-- | components/webdriver_server/Cargo.toml | 3 | ||||
-rw-r--r-- | components/webdriver_server/lib.rs | 155 | ||||
-rw-r--r-- | components/webdriver_traits/Cargo.toml | 11 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 13 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 13 |
20 files changed, 273 insertions, 122 deletions
diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 54be36997f9..944686bf559 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -37,9 +37,6 @@ path = "../style" [dependencies.util] path = "../util" -[dependencies.webdriver_traits] -path = "../webdriver_traits" - [dependencies.devtools_traits] path = "../devtools_traits" diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 6b79722b7e4..8c4b2557cd8 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -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. diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index fcf3a84d44a..785a594aed9 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -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; diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index fa70fe5463e..53d152d60ec 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -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"
\ No newline at end of file diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 8706a807cab..6680804c3ef 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -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 diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 73c5255ddca..52fa7fe4817 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -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; diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs new file mode 100644 index 00000000000..7921bb0a156 --- /dev/null +++ b/components/msg/webdriver_msg.rs @@ -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; diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 80c4ecdc4e4..400fb35d462 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -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" diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 21e9bbc28f2..d8df4ad9c73 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -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 { diff --git a/components/script/lib.rs b/components/script/lib.rs index b71acd76363..46e50c66ddb 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -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; diff --git a/components/script/script_task.rs b/components/script/script_task.rs index ff13cc12ff0..1d7b65ba1b4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -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) => diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 6d6c7313a7c..5ba227df192 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -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()) { diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 9b41ae54ec2..d33e0ff6b98 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -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" diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 188c5effe28..960e60a6af0 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -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; diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index c611d89dc5a..523aee5d030 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -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]] diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index 7eb6135c696..9124d8bcf1f 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -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" diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 4ac4d09c078..3608c1e8cfb 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -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(), diff --git a/components/webdriver_traits/Cargo.toml b/components/webdriver_traits/Cargo.toml deleted file mode 100644 index e27f0e4cf74..00000000000 --- a/components/webdriver_traits/Cargo.toml +++ /dev/null @@ -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" diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 684700375e0..f151d2d65a3 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -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]] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 3c01648decc..3c401923a84 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -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]] |