зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6ed17c03e5
Коммит
35d7b3b717
|
@ -37,9 +37,6 @@ path = "../style"
|
|||
[dependencies.util]
|
||||
path = "../util"
|
||||
|
||||
[dependencies.webdriver_traits]
|
||||
path = "../webdriver_traits"
|
||||
|
||||
[dependencies.devtools_traits]
|
||||
path = "../devtools_traits"
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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"
|
|
@ -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]]
|
||||
|
|
|
@ -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]]
|
||||
|
|
Загрузка…
Ссылка в новой задаче