GenericChannel: Migrate compositor channels to GenericChannel (#38782)

Besides migrating the channel to GenericChannel, this PR adds
`routed_channel_with_local_sender()` to `generic_channel`. This is for
existing use-cases, where we want to provide both an IPC capable
GenericSender, as well as a crossbeam Sender, for efficient sending if
the sender is in the same process.

Testing: All of our channels should send / receive at least some
messages during WPT tests.

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
Jonathan Schwender 2025-08-25 13:05:21 +02:00 committed by GitHub
parent 7441944e36
commit fb1c0a4c48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 98 additions and 43 deletions

View file

@ -23,6 +23,7 @@ pub mod viewport_description;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use base::generic_channel::GenericSender;
use bitflags::bitflags;
use display_list::CompositorDisplayListInfo;
use embedder_traits::ScreenGeometry;
@ -44,7 +45,12 @@ use crate::viewport_description::ViewportDescription;
/// Sends messages to the compositor.
#[derive(Clone)]
pub struct CompositorProxy {
pub sender: Sender<CompositorMsg>,
/// A sender optimised for sending in the local process.
/// The type is a Result to match the API of ipc_channel after routing,
/// which contains a Result to propagate deserialization errors to the
/// recipient.
/// The field is private to hide the inner `Result` type.
sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
/// Access to [`Self::sender`] that is possible to send across an IPC
/// channel. These messages are routed via the router thread to
/// [`Self::sender`].
@ -52,6 +58,20 @@ pub struct CompositorProxy {
pub event_loop_waker: Box<dyn EventLoopWaker>,
}
impl CompositorProxy {
pub fn new(
local_process_sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
cross_process_compositor_api: CrossProcessCompositorApi,
event_loop_waker: Box<dyn EventLoopWaker>,
) -> Self {
Self {
sender: local_process_sender,
cross_process_compositor_api,
event_loop_waker,
}
}
}
impl OpaqueSender<CompositorMsg> for CompositorProxy {
fn send(&self, message: CompositorMsg) {
CompositorProxy::send(self, message)
@ -60,7 +80,7 @@ impl OpaqueSender<CompositorMsg> for CompositorProxy {
impl CompositorProxy {
pub fn send(&self, msg: CompositorMsg) {
if let Err(err) = self.sender.send(msg) {
if let Err(err) = self.sender.send(Ok(msg)) {
warn!("Failed to send response ({:?}).", err);
}
self.event_loop_waker.wake();
@ -170,18 +190,18 @@ pub struct CompositionPipeline {
/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
pub struct CrossProcessCompositorApi(pub IpcSender<CompositorMsg>);
pub struct CrossProcessCompositorApi(pub GenericSender<CompositorMsg>);
impl CrossProcessCompositorApi {
/// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other
/// end to use for unit testing.
pub fn dummy() -> Self {
let (sender, _) = ipc::channel().unwrap();
let (sender, _) = base::generic_channel::channel().unwrap();
Self(sender)
}
/// Get the sender for this proxy.
pub fn sender(&self) -> &IpcSender<CompositorMsg> {
pub fn sender(&self) -> &GenericSender<CompositorMsg> {
&self.0
}