mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
use ipc router in webdriver
This commit is contained in:
parent
17f423723c
commit
9ddba756bf
1 changed files with 40 additions and 27 deletions
|
@ -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]
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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"))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue