From 9ddba756bfb19c9513eb84a80674aa4c23231799 Mon Sep 17 00:00:00 2001 From: Gregory Terzian Date: Mon, 19 Aug 2019 21:57:12 +0200 Subject: [PATCH] use ipc router in webdriver --- components/webdriver_server/lib.rs | 67 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 0bd7d140c325..03a15db335d2 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -6,6 +6,8 @@ #![crate_type = "rlib"] #![deny(unsafe_code)] +#[macro_use] +extern crate crossbeam_channel; #[macro_use] extern crate log; #[macro_use] @@ -19,11 +21,12 @@ mod capabilities; use crate::actions::InputSourceState; use base64; use capabilities::ServoCapabilities; -use crossbeam_channel::Sender; +use crossbeam_channel::{after, unbounded, Receiver, Sender}; use euclid::{Rect, Size2D}; use hyper::Method; 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 msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection}; use pixels::PixelFormat; @@ -171,6 +174,14 @@ impl WebDriverSession { } 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, + /// 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, session: Option, constellation_chan: Sender, resize_timeout: u32, @@ -371,7 +382,17 @@ impl<'de> Visitor<'de> for TupleVecMapVisitor { impl Handler { pub fn new(constellation_chan: Sender) -> 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 { + load_status_sender, + load_status_receiver, session: None, constellation_chan: constellation_chan, resize_timeout: 500, @@ -613,35 +634,26 @@ impl Handler { 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 cmd_msg = - WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, sender.clone()); + let cmd_msg = WebDriverCommandMsg::LoadUrl( + top_level_browsing_context_id, + load_data, + self.load_status_sender.clone(), + ); self.constellation_chan .send(ConstellationMsg::WebDriverCommand(cmd_msg)) .unwrap(); - self.wait_for_load(sender, receiver) + self.wait_for_load() } - fn wait_for_load( - &self, - sender: IpcSender, - receiver: IpcReceiver, - ) -> WebDriverResult { + fn wait_for_load(&self) -> WebDriverResult { let timeout = self.session()?.load_timeout; - thread::spawn(move || { - thread::sleep(Duration::from_millis(timeout)); - let _ = sender.send(LoadStatus::LoadTimeout); - }); - - // 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")) - }, + select! { + recv(self.load_status_receiver) -> _ => Ok(WebDriverResponse::Void), + recv(after(Duration::from_millis(timeout))) -> _ => Err( + WebDriverError::new(ErrorStatus::Timeout, "Load timed out") + ), } } @@ -775,14 +787,15 @@ impl Handler { fn handle_refresh(&self) -> WebDriverResult { 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, sender.clone()); + let cmd_msg = WebDriverCommandMsg::Refresh( + top_level_browsing_context_id, + self.load_status_sender.clone(), + ); self.constellation_chan .send(ConstellationMsg::WebDriverCommand(cmd_msg)) .unwrap(); - self.wait_for_load(sender, receiver) + self.wait_for_load() } fn handle_title(&self) -> WebDriverResult {