Implement some contact and request interfaces

Empathy still isn't happy, but it's going to take some debugging to
work out why. I suspect it requires one of the "optional" interfaces
in practice... but which one?
This commit is contained in:
2020-05-13 01:46:35 +01:00
parent b6fbcfeeb8
commit 5eea970cf7

View File

@@ -2,7 +2,7 @@ use crate::telepathy;
use dbus::blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection};
use dbus::channel::Sender;
use dbus::message::SignalArgs;
use dbus::tree;
use dbus::{arg, tree};
use dc::config::Config;
use dc::context::Context;
@@ -68,7 +68,8 @@ impl Connection {
let msgq = Arc::new(Mutex::new(VecDeque::<dbus::Message>::new()));
let id2 = id.clone();
let msgq2 = msgq.clone();
// Use this if we need to send messages in response to DC events:
// let msgq2 = msgq.clone();
let f = move |_c: &Context, e: Event| {
match e {
Event::Info(msg) => println!("Connection<{}>: INFO: {}", id2, msg),
@@ -144,11 +145,26 @@ impl Connection {
let c_rc = std::rc::Rc::new(self);
let f = tree::Factory::new_fn::<()>();
let iface = telepathy::connection_server(&f, (), move |_| c_rc.clone());
let mut tree = f.tree(());
tree = tree.add(f.object_path(path, ()).introspectable().add(iface));
let c_rc1 = c_rc.clone();
let conn_iface = telepathy::connection_server(&f, (), move |_| c_rc1.clone());
let c_rc2 = c_rc.clone();
let contacts_iface =
telepathy::connection_interface_contacts_server(&f, (), move |_| c_rc2.clone());
let c_rc3 = c_rc.clone();
let requests_iface =
telepathy::connection_interface_requests_server(&f, (), move |_| c_rc3.clone());
tree = tree.add(
f.object_path(path.clone(), ())
.introspectable()
.add(conn_iface)
.add(contacts_iface)
.add(requests_iface),
);
tree = tree.add(f.object_path("/", ()).introspectable());
// Setup DBus connection
@@ -219,6 +235,18 @@ impl AsRef<dyn telepathy::Connection + 'static> for std::rc::Rc<Connection> {
}
}
impl AsRef<dyn telepathy::ConnectionInterfaceContacts + 'static> for std::rc::Rc<Connection> {
fn as_ref(&self) -> &(dyn telepathy::ConnectionInterfaceContacts + 'static) {
&**self
}
}
impl AsRef<dyn telepathy::ConnectionInterfaceRequests + 'static> for std::rc::Rc<Connection> {
fn as_ref(&self) -> &(dyn telepathy::ConnectionInterfaceRequests + 'static) {
&**self
}
}
impl telepathy::Connection for Connection {
// In connect(), we start the threads that drive the deltachat context
fn connect(&self) -> Result<(), tree::MethodErr> {
@@ -443,6 +471,128 @@ impl telepathy::Connection for Connection {
}
}
impl telepathy::ConnectionInterfaceContacts for Connection {
fn get_contact_attributes(
&self,
handles: Vec<u32>,
interfaces: Vec<&str>,
hold: bool,
) -> Result<HashMap<u32, HashMap<String, super::Variant>>, tree::MethodErr> {
println!(
"Connection<{}>::get_contact_attributes({:?}, {:?}, {})",
self.id, handles, interfaces, hold
);
let mut out = HashMap::<u32, HashMap<String, super::Variant>>::new();
for id in handles.iter() {
// FIXME: work out how to use get_all
let contact = match dc::contact::Contact::get_by_id(&self.ctx.read().unwrap(), *id) {
Ok(c) => c,
Err(_e) => continue, // FIXME: Ignore the error. Whatevs.
};
let mut props = HashMap::<String, super::Variant>::new();
// This is mandatory
props.insert(
"org.freedesktop.Telepathy.Connection/contact-id".to_string(),
arg::Variant(Box::new(contact.get_display_name().to_string())),
);
// We don't advertise this interface but empathy is being weird.
// The empty string means "no avatar"
props.insert(
"org.freedesktop.Telepathy.Connection.Interface.Avatars/token".to_string(),
arg::Variant(Box::new("".to_string())),
);
out.insert(*id, props);
}
Ok(out)
}
fn get_contact_by_id(
&self,
identifier: &str,
interfaces: Vec<&str>,
) -> Result<
(
u32,
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
),
tree::MethodErr,
> {
println!(
"Connection<{}>::get_contact_by_id({}, {:?})",
self.id, identifier, interfaces
);
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
}
fn contact_attribute_interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
println!("Connection<{}>::contact_attribute_interfaces()", self.id);
Ok(vec![])
}
}
impl telepathy::ConnectionInterfaceRequests for Connection {
fn create_channel(
&self,
request: ::std::collections::HashMap<&str, arg::Variant<Box<dyn arg::RefArg>>>,
) -> Result<
(
dbus::Path<'static>,
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
),
tree::MethodErr,
> {
println!("Connection<{}>::create_channel({:?})", self.id, request);
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
}
fn ensure_channel(
&self,
request: ::std::collections::HashMap<&str, arg::Variant<Box<dyn arg::RefArg>>>,
) -> Result<
(
bool,
dbus::Path<'static>,
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
),
tree::MethodErr,
> {
println!("Connection<{}>::ensure_channel({:?})", self.id, request);
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
}
fn channels(
&self,
) -> Result<
Vec<(
dbus::Path<'static>,
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
)>,
tree::MethodErr,
> {
println!("Connection<{}>::channels()", self.id);
Ok(vec![])
}
fn requestable_channel_classes(
&self,
) -> Result<
Vec<(
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
Vec<String>,
)>,
tree::MethodErr,
> {
println!("Connection<{}>::requestable_channel_classes()", self.id);
Ok(super::requestables())
}
}
fn escape_one(b: u8) -> String {
format!("_{:0<2x}", b)
}