aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Graham <james@hoppipolla.co.uk>2015-05-11 14:47:10 +0100
committerJames Graham <james@hoppipolla.co.uk>2015-06-01 23:18:55 +0100
commit49f1b13ad968467e442d9bc7bc1ee737365e1f5d (patch)
tree6459e79dab04095889035a8aad9b7d933f294077
parentc724444ccb85551b5a0a581d673875ec9bce3d1f (diff)
downloadservo-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.toml3
-rw-r--r--components/compositing/constellation.rs30
-rw-r--r--components/compositing/lib.rs1
-rw-r--r--components/msg/Cargo.toml4
-rw-r--r--components/msg/constellation_msg.rs10
-rw-r--r--components/msg/lib.rs3
-rw-r--r--components/msg/webdriver_msg.rs56
-rw-r--r--components/script/Cargo.toml3
-rw-r--r--components/script/dom/window.rs29
-rw-r--r--components/script/lib.rs1
-rw-r--r--components/script/script_task.rs4
-rw-r--r--components/script/webdriver_handlers.rs37
-rw-r--r--components/script_traits/Cargo.toml3
-rw-r--r--components/script_traits/lib.rs3
-rw-r--r--components/servo/Cargo.lock13
-rw-r--r--components/webdriver_server/Cargo.toml3
-rw-r--r--components/webdriver_server/lib.rs155
-rw-r--r--components/webdriver_traits/Cargo.toml11
-rw-r--r--ports/cef/Cargo.lock13
-rw-r--r--ports/gonk/Cargo.lock13
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]]