Skip to content

Commit

Permalink
use ipc router in webdriver
Browse files Browse the repository at this point in the history
  • Loading branch information
gterzian committed Aug 20, 2019
1 parent 17f4237 commit 9ddba75
Showing 1 changed file with 40 additions and 27 deletions.
67 changes: 40 additions & 27 deletions components/webdriver_server/lib.rs
Expand Up @@ -6,6 +6,8 @@
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![deny(unsafe_code)] #![deny(unsafe_code)]


#[macro_use]
extern crate crossbeam_channel;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[macro_use] #[macro_use]
Expand All @@ -19,11 +21,12 @@ mod capabilities;
use crate::actions::InputSourceState; use crate::actions::InputSourceState;
use base64; use base64;
use capabilities::ServoCapabilities; use capabilities::ServoCapabilities;
use crossbeam_channel::Sender; use crossbeam_channel::{after, unbounded, Receiver, Sender};
use euclid::{Rect, Size2D}; use euclid::{Rect, Size2D};
use hyper::Method; use hyper::Method;
use image::{DynamicImage, ImageFormat, RgbImage}; use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use keyboard_types::webdriver::send_keys; use keyboard_types::webdriver::send_keys;
use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection}; use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection};
use pixels::PixelFormat; use pixels::PixelFormat;
Expand Down Expand Up @@ -171,6 +174,14 @@ impl WebDriverSession {
} }


struct Handler { struct Handler {
/// The threaded receiver on which we can block for a load-status.
/// It will receive messages sent on the load_status_sender,
/// and forwarded by the IPC router.
load_status_receiver: Receiver<LoadStatus>,
/// The IPC sender which we can clone and pass along to the constellation,
/// for it to send us a load-status. Messages sent on it
/// will be forwarded to the load_status_receiver.
load_status_sender: IpcSender<LoadStatus>,
session: Option<WebDriverSession>, session: Option<WebDriverSession>,
constellation_chan: Sender<ConstellationMsg>, constellation_chan: Sender<ConstellationMsg>,
resize_timeout: u32, resize_timeout: u32,
Expand Down Expand Up @@ -371,7 +382,17 @@ impl<'de> Visitor<'de> for TupleVecMapVisitor {


impl Handler { impl Handler {
pub fn new(constellation_chan: Sender<ConstellationMsg>) -> Handler { pub fn new(constellation_chan: Sender<ConstellationMsg>) -> Handler {
// Create a pair of both an IPC and a threaded channel,
// keep the IPC sender to clone and pass to the constellation for each load,
// and keep a threaded receiver to block on an incoming load-status.
// Pass the others to the IPC router so that IPC messages are forwarded to the threaded receiver.
// We need to use the router because IPC does not come with a timeout on receive/select.
let (load_status_sender, receiver) = ipc::channel().unwrap();
let (sender, load_status_receiver) = unbounded();
ROUTER.route_ipc_receiver_to_crossbeam_sender(receiver, sender);
Handler { Handler {
load_status_sender,
load_status_receiver,
session: None, session: None,
constellation_chan: constellation_chan, constellation_chan: constellation_chan,
resize_timeout: 500, resize_timeout: 500,
Expand Down Expand Up @@ -613,35 +634,26 @@ impl Handler {


let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id; let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;


let (sender, receiver) = ipc::channel().unwrap();

let load_data = LoadData::new(LoadOrigin::WebDriver, url, None, None, None); let load_data = LoadData::new(LoadOrigin::WebDriver, url, None, None, None);
let cmd_msg = let cmd_msg = WebDriverCommandMsg::LoadUrl(
WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, sender.clone()); top_level_browsing_context_id,
load_data,
self.load_status_sender.clone(),
);
self.constellation_chan self.constellation_chan
.send(ConstellationMsg::WebDriverCommand(cmd_msg)) .send(ConstellationMsg::WebDriverCommand(cmd_msg))
.unwrap(); .unwrap();


self.wait_for_load(sender, receiver) self.wait_for_load()
} }


fn wait_for_load( fn wait_for_load(&self) -> WebDriverResult<WebDriverResponse> {
&self,
sender: IpcSender<LoadStatus>,
receiver: IpcReceiver<LoadStatus>,
) -> WebDriverResult<WebDriverResponse> {
let timeout = self.session()?.load_timeout; let timeout = self.session()?.load_timeout;
thread::spawn(move || { select! {
thread::sleep(Duration::from_millis(timeout)); recv(self.load_status_receiver) -> _ => Ok(WebDriverResponse::Void),
let _ = sender.send(LoadStatus::LoadTimeout); recv(after(Duration::from_millis(timeout))) -> _ => Err(
}); WebDriverError::new(ErrorStatus::Timeout, "Load timed out")

),
// wait to get a load event
match receiver.recv().unwrap() {
LoadStatus::LoadComplete => Ok(WebDriverResponse::Void),
LoadStatus::LoadTimeout => {
Err(WebDriverError::new(ErrorStatus::Timeout, "Load timed out"))
},
} }
} }


Expand Down Expand Up @@ -775,14 +787,15 @@ impl Handler {
fn handle_refresh(&self) -> WebDriverResult<WebDriverResponse> { fn handle_refresh(&self) -> WebDriverResult<WebDriverResponse> {
let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id; let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;


let (sender, receiver) = ipc::channel().unwrap(); let cmd_msg = WebDriverCommandMsg::Refresh(

top_level_browsing_context_id,
let cmd_msg = WebDriverCommandMsg::Refresh(top_level_browsing_context_id, sender.clone()); self.load_status_sender.clone(),
);
self.constellation_chan self.constellation_chan
.send(ConstellationMsg::WebDriverCommand(cmd_msg)) .send(ConstellationMsg::WebDriverCommand(cmd_msg))
.unwrap(); .unwrap();


self.wait_for_load(sender, receiver) self.wait_for_load()
} }


fn handle_title(&self) -> WebDriverResult<WebDriverResponse> { fn handle_title(&self) -> WebDriverResult<WebDriverResponse> {
Expand Down

0 comments on commit 9ddba75

Please sign in to comment.