Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using IPC to handle navigations #222

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = ["verso", "versoview_messages"]
ipc-channel = "0.19"
serde = { version = "1.0", features = ["derive"] }
url = { version = "2.5.2", features = ["serde"] }
log = "0.4"

[package]
name = "versoview"
Expand Down Expand Up @@ -63,7 +64,7 @@ glutin = "0.32.0"
glutin-winit = "0.5.0"
ipc-channel = { workspace = true }
keyboard-types = "0.7"
log = "0.4"
log = { workspace = true }
raw-window-handle = { version = "0.6", features = ["std"] }
rustls = { version = "0.23", default-features = false, features = ["ring"] }
sparkle = "0.1.26"
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ pub enum Error {
/// Glutin errors.
#[error(transparent)]
GlutinError(#[from] glutin::error::Error),
/// IPC errors.
#[error(transparent)]
IpcError(#[from] ipc_channel::ipc::IpcError),
}
10 changes: 9 additions & 1 deletion src/verso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ impl Verso {
}

/// Handle message came from webview controller.
pub fn handle_incoming_webview_message(&self, message: ControllerMessage) {
pub fn handle_incoming_webview_message(&mut self, message: ControllerMessage) {
match message {
ControllerMessage::NavigateTo(to_url) => {
if let Some(webview_id) =
Expand All @@ -596,6 +596,14 @@ impl Verso {
);
}
}
ControllerMessage::OnNavigationStarting(sender) => {
if let Some((window, _)) = self.windows.values_mut().next() {
window
.event_listeners
.on_navigation_starting
.replace(sender);
}
}
_ => {}
}
}
Expand Down
26 changes: 23 additions & 3 deletions src/webview/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,15 @@ impl Window {
let _ = rx.recv();
}
}
EmbedderMsg::AllowNavigationRequest(id, _url) => {
// TODO should provide a API for users to check url
send_to_constellation(sender, ConstellationMsg::AllowNavigationResponse(id, true));
EmbedderMsg::AllowNavigationRequest(id, url) => {
let allow = match self.allow_navigation(url) {
Ok(allow) => allow,
Err(e) => {
log::error!("Error when calling navigation handler: {e}");
true
}
};
send_to_constellation(sender, ConstellationMsg::AllowNavigationResponse(id, allow));
}
EmbedderMsg::GetClipboardContents(sender) => {
let contents = clipboard
Expand Down Expand Up @@ -599,4 +605,18 @@ impl Window {
}
false
}

fn allow_navigation(&self, url: ServoUrl) -> crate::Result<bool> {
if let Some(ref sender) = self.event_listeners.on_navigation_starting {
let (result_sender, receiver) =
ipc::channel::<bool>().map_err(|e| ipc::IpcError::Io(e))?;
sender
.send((url.into_url(), result_sender))
.map_err(|e| ipc::IpcError::Bincode(e))?;
let result = receiver.recv()?;
Ok(result)
} else {
Ok(true)
}
}
}
10 changes: 10 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use script_traits::{
};
use script_traits::{TouchEventType, WheelDelta, WheelMode};
use servo_url::ServoUrl;
use versoview_messages::OnNavigationStartingPayload;
use webrender_api::{
units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, LayoutVector2D},
ScrollLocation,
Expand Down Expand Up @@ -57,6 +58,11 @@ const PANEL_HEIGHT: f64 = 50.0;
const TAB_HEIGHT: f64 = 30.0;
const PANEL_PADDING: f64 = 4.0;

#[derive(Default)]
pub(crate) struct EventListeners {
pub(crate) on_navigation_starting: Option<OnNavigationStartingPayload>,
}

/// A Verso window is a Winit window containing several web views.
pub struct Window {
/// Access to Winit window
Expand All @@ -67,6 +73,8 @@ pub struct Window {
pub(crate) panel: Option<Panel>,
/// The WebView of this window.
// pub(crate) webview: Option<WebView>,
/// Event listeners registered from the webview controller
pub(crate) event_listeners: EventListeners,
/// The mouse physical position in the web view.
mouse_position: Cell<Option<PhysicalPosition<f64>>>,
/// Modifiers state of the keyboard.
Expand Down Expand Up @@ -126,6 +134,7 @@ impl Window {
window,
surface,
panel: None,
event_listeners: Default::default(),
mouse_position: Default::default(),
modifiers_state: Cell::new(ModifiersState::default()),
resizing: false,
Expand Down Expand Up @@ -168,6 +177,7 @@ impl Window {
surface,
panel: None,
// webview: None,
event_listeners: Default::default(),
mouse_position: Default::default(),
modifiers_state: Cell::new(ModifiersState::default()),
resizing: false,
Expand Down
1 change: 1 addition & 0 deletions verso/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ edition = "2021"
ipc-channel = { workspace = true }
serde = { workspace = true }
url = { workspace = true }
log = { workspace = true }
versoview_messages = { path = "../versoview_messages" }
63 changes: 58 additions & 5 deletions verso/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
use std::{path::Path, process::Command};
use log::error;
use std::{
path::Path,
process::Command,
sync::{Arc, Mutex},
};
use versoview_messages::ControllerMessage;

use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
use ipc_channel::{
ipc::{self, IpcOneShotServer, IpcSender},
router::ROUTER,
};

pub struct VersoviewController(IpcSender<ControllerMessage>);
#[derive(Default)]
struct EventListeners {
on_navigation_starting: Arc<Mutex<Option<Box<dyn Fn(url::Url) -> bool + Send + 'static>>>>,
}

pub struct VersoviewController {
sender: IpcSender<ControllerMessage>,
event_listeners: EventListeners,
}

impl VersoviewController {
/// Create a new verso instance and get the controller to it
Expand All @@ -17,11 +33,48 @@ impl VersoviewController {
.spawn()
.unwrap();
let (_, sender) = server.accept().unwrap();
Self(sender)
Self {
sender,
event_listeners: EventListeners::default(),
}
}

/// Navigate to url
pub fn navigate(&self, url: url::Url) -> Result<(), Box<ipc_channel::ErrorKind>> {
self.0.send(ControllerMessage::NavigateTo(url))
self.sender.send(ControllerMessage::NavigateTo(url))
}

/// Listen on navigation starting triggered by user click on a link,
/// return a boolean in the callback to decide whether or not allowing this navigation
pub fn on_navigation_starting(
&self,
callback: impl Fn(url::Url) -> bool + Send + 'static,
) -> Result<(), Box<ipc_channel::ErrorKind>> {
if self
.event_listeners
.on_navigation_starting
.lock()
.unwrap()
.replace(Box::new(callback))
.is_some()
{
return Ok(());
}
let cb = self.event_listeners.on_navigation_starting.clone();
let (sender, receiver) = ipc::channel::<(url::Url, ipc::IpcSender<bool>)>()?;
self.sender
.send(ControllerMessage::OnNavigationStarting(sender))?;
ROUTER.add_typed_route(
receiver,
Box::new(move |message| match message {
Ok((url, result_sender)) => {
if let Err(e) = result_sender.send(cb.lock().unwrap().as_ref().unwrap()(url)) {
error!("Error while sending back OnNavigationStarting result: {e}");
}
}
Err(e) => error!("Error while receiving OnNavigationStarting message: {e}"),
}),
);
Ok(())
}
}
6 changes: 6 additions & 0 deletions verso/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ fn main() {
versoview_path,
url::Url::parse("https://example.com").unwrap(),
);
controller
.on_navigation_starting(|url| {
dbg!(url);
true
})
.unwrap();
sleep(Duration::from_secs(10));
dbg!(controller
.navigate(url::Url::parse("https://docs.rs").unwrap())
Expand Down
4 changes: 4 additions & 0 deletions versoview_messages/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use ipc_channel::ipc;
use serde::{Deserialize, Serialize};

pub type OnNavigationStartingPayload = ipc::IpcSender<(url::Url, ipc::IpcSender<bool>)>;

#[derive(Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ControllerMessage {
NavigateTo(url::Url),
OnNavigationStarting(OnNavigationStartingPayload),
}
Loading