зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #5610 - Add enough Webdriver support to enable Get() (from jgraham:jgraham/webdriver-get); r=jdm
This is incomplete in several ways: * It assumes that there's only one constellation (i.e. top level browsing context), ever. * The session support is very basic indeed (no capabilities) * Passing channels over channels may not sit well with IPC * The error handling is mostly missing Source-Repo: https://github.com/servo/servo Source-Revision: af2f46bddad7a0e87a46fc3e303f15b4343226c7
This commit is contained in:
Родитель
901eb35f52
Коммит
50ca4e6223
|
@ -31,6 +31,9 @@ path = "../net_traits"
|
|||
[dependencies.util]
|
||||
path = "../util"
|
||||
|
||||
[dependencies.webdriver_server]
|
||||
path = "../webdriver_server"
|
||||
|
||||
[dependencies.devtools_traits]
|
||||
path = "../devtools_traits"
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use std::collections::HashMap;
|
|||
use std::io::{self, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::replace;
|
||||
use std::sync::mpsc::{Receiver, channel};
|
||||
use std::sync::mpsc::{Sender, Receiver, channel};
|
||||
use url::Url;
|
||||
use util::cursor::Cursor;
|
||||
use util::geometry::PagePx;
|
||||
|
@ -383,6 +383,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
subpage_id,
|
||||
event);
|
||||
}
|
||||
ConstellationMsg::GetRootPipeline(resp_chan) => {
|
||||
debug!("constellation got get root pipeline message");
|
||||
self.handle_get_root_pipeline(resp_chan);
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -679,6 +683,14 @@ 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| {
|
||||
let frame = self.frames.get(&frame_id).unwrap();
|
||||
frame.current
|
||||
});
|
||||
resp_chan.send(pipeline_id).unwrap();
|
||||
}
|
||||
|
||||
fn add_or_replace_pipeline_in_frame_tree(&mut self, frame_change: FrameChange) {
|
||||
let evicted_frames = match frame_change.old_pipeline_id {
|
||||
Some(old_pipeline_id) => {
|
||||
|
|
|
@ -27,6 +27,7 @@ extern crate net_traits;
|
|||
#[macro_use]
|
||||
extern crate util;
|
||||
extern crate gleam;
|
||||
extern crate webdriver_server;
|
||||
|
||||
extern crate libc;
|
||||
extern crate time;
|
||||
|
|
|
@ -218,6 +218,8 @@ pub enum Msg {
|
|||
ChangeRunningAnimationsState(PipelineId, bool),
|
||||
/// 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>>)
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
|
||||
|
|
|
@ -109,6 +109,7 @@ dependencies = [
|
|||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webdriver_server 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1004,7 +1005,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webdriver"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd"
|
||||
dependencies = [
|
||||
"hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1017,6 +1018,11 @@ dependencies = [
|
|||
name = "webdriver_server"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"msg 0.0.1",
|
||||
"rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)",
|
||||
]
|
||||
|
||||
|
|
|
@ -104,10 +104,6 @@ impl Browser {
|
|||
devtools::start_server(port)
|
||||
});
|
||||
|
||||
if let Some(port) = opts.webdriver_port {
|
||||
webdriver_server::start_server(port);
|
||||
}
|
||||
|
||||
// Create the constellation, which maintains the engine
|
||||
// pipelines, including the script and layout threads, as well
|
||||
// as the navigation context.
|
||||
|
@ -118,6 +114,10 @@ impl Browser {
|
|||
mem_profiler_chan.clone(),
|
||||
shared_task_pool);
|
||||
|
||||
if let Some(port) = opts.webdriver_port {
|
||||
webdriver_server::start_server(port, constellation_chan.clone());
|
||||
};
|
||||
|
||||
// The compositor coordinates with the client window to create the final
|
||||
// rendered page and display it somewhere.
|
||||
let compositor = CompositorTask::create(window,
|
||||
|
|
|
@ -7,5 +7,16 @@ authors = ["The Servo Project Developers"]
|
|||
name = "webdriver_server"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.msg]
|
||||
path = "../msg"
|
||||
|
||||
[dependencies.util]
|
||||
path = "../util"
|
||||
|
||||
[dependencies.webdriver]
|
||||
git = "https://github.com/jgraham/webdriver-rust.git"
|
||||
|
||||
[dependencies]
|
||||
rustc-serialize="0.3.4"
|
||||
url = "0.2.16"
|
||||
uuid = "0.1.11"
|
|
@ -6,27 +6,125 @@
|
|||
#![crate_type = "rlib"]
|
||||
|
||||
#![feature(net)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
extern crate webdriver;
|
||||
extern crate msg;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
extern crate "rustc-serialize" as rustc_serialize;
|
||||
extern crate uuid;
|
||||
|
||||
use webdriver::command::WebDriverMessage;
|
||||
use webdriver::error::WebDriverResult;
|
||||
use webdriver::response::WebDriverResponse;
|
||||
use msg::constellation_msg::{ConstellationChan, LoadData};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use url::Url;
|
||||
use webdriver::command::{WebDriverMessage, WebDriverCommand};
|
||||
use webdriver::command::GetParameters;
|
||||
use webdriver::response::{
|
||||
WebDriverResponse, NewSessionResponse, ValueResponse};
|
||||
use webdriver::server::{self, WebDriverHandler, Session};
|
||||
use webdriver::error::{WebDriverResult, WebDriverError, ErrorStatus};
|
||||
use util::task::spawn_named;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
use std::net::IpAddr;
|
||||
use rustc_serialize::json::{Json, ToJson};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub fn start_server(port: u16) {
|
||||
server::start(IpAddr::new_v4(0, 0, 0, 0), port, Handler);
|
||||
pub fn start_server(port: u16, constellation_chan: ConstellationChan) {
|
||||
let handler = Handler::new(constellation_chan);
|
||||
|
||||
spawn_named("WebdriverHttpServer".to_owned(), move || {
|
||||
server::start(IpAddr::new_v4(0, 0, 0, 0), port, handler);
|
||||
});
|
||||
}
|
||||
|
||||
struct Handler;
|
||||
struct WebdriverSession {
|
||||
id: Uuid
|
||||
}
|
||||
|
||||
impl WebDriverHandler for Handler {
|
||||
fn handle_command(&mut self, _session: &Option<Session>, _msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> {
|
||||
struct Handler {
|
||||
session: Option<WebdriverSession>,
|
||||
constellation_chan: ConstellationChan
|
||||
}
|
||||
|
||||
impl WebdriverSession {
|
||||
pub fn new() -> WebdriverSession {
|
||||
WebdriverSession {
|
||||
id: Uuid::new_v4()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn new(constellation_chan: ConstellationChan) -> Handler {
|
||||
Handler {
|
||||
session: None,
|
||||
constellation_chan: constellation_chan
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_new_session(&mut self) -> WebDriverResult<WebDriverResponse> {
|
||||
if self.session.is_none() {
|
||||
let session = WebdriverSession::new();
|
||||
let rv = Ok(WebDriverResponse::NewSession(
|
||||
NewSessionResponse::new(
|
||||
session.id.to_string(),
|
||||
Json::Object(BTreeMap::new()))));
|
||||
self.session = Some(session);
|
||||
rv
|
||||
} else {
|
||||
Err(WebDriverError::new(ErrorStatus::UnknownError,
|
||||
"Session already created"))
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_get(&self, parameters: &GetParameters) -> WebDriverResult<WebDriverResponse> {
|
||||
let url = match Url::parse(¶meters.url[..]) {
|
||||
Ok(url) => url,
|
||||
Err(_) => return Err(WebDriverError::new(ErrorStatus::InvalidArgument,
|
||||
"Invalid URL"))
|
||||
};
|
||||
|
||||
let (sender, reciever) = channel();
|
||||
let ConstellationChan(ref const_chan) = self.constellation_chan;
|
||||
const_chan.send(ConstellationMsg::GetRootPipeline(sender)).unwrap();
|
||||
|
||||
let pipeline_id = reciever.recv().unwrap().unwrap();
|
||||
|
||||
let load_data = LoadData::new(url);
|
||||
const_chan.send(ConstellationMsg::LoadUrl(pipeline_id, load_data)).unwrap();
|
||||
//TODO: Now we ought to wait until we get a load event
|
||||
Ok(WebDriverResponse::Void)
|
||||
}
|
||||
|
||||
fn delete_session(&mut self, _session: &Option<Session>) {
|
||||
fn handle_get_window_handle(&self) -> WebDriverResult<WebDriverResponse> {
|
||||
// For now we assume there's only one window so just use the session
|
||||
// id as the window id
|
||||
let handle = self.session.as_ref().unwrap().id.to_string();
|
||||
Ok(WebDriverResponse::Generic(ValueResponse::new(handle.to_json())))
|
||||
}
|
||||
}
|
||||
|
||||
impl WebDriverHandler for Handler {
|
||||
fn handle_command(&mut self, _session: &Option<Session>, msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> {
|
||||
|
||||
match msg.command {
|
||||
WebDriverCommand::NewSession => self.handle_new_session(),
|
||||
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
|
||||
WebDriverCommand::GetWindowHandle => self.handle_get_window_handle(),
|
||||
_ => Err(WebDriverError::new(ErrorStatus::UnsupportedOperation,
|
||||
"Command not implemented"))
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_session(&mut self, _session: &Option<Session>) {
|
||||
self.session = None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ dependencies = [
|
|||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webdriver_server 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1007,7 +1008,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webdriver"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd"
|
||||
dependencies = [
|
||||
"hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1020,6 +1021,11 @@ dependencies = [
|
|||
name = "webdriver_server"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"msg 0.0.1",
|
||||
"rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)",
|
||||
]
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ dependencies = [
|
|||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webdriver_server 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -923,7 +924,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webdriver"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc"
|
||||
source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd"
|
||||
dependencies = [
|
||||
"hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -936,6 +937,11 @@ dependencies = [
|
|||
name = "webdriver_server"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"msg 0.0.1",
|
||||
"rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)",
|
||||
]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче