Skip to content

Commit 33dbca1

Browse files
committed
feat: allow sending webxdc update from broadcase subscribers
1 parent d9474a6 commit 33dbca1

3 files changed

Lines changed: 103 additions & 7 deletions

File tree

src/chat.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,7 +2691,9 @@ async fn prepare_send_msg(
26912691
CantSendReason::InBroadcast => {
26922692
matches!(
26932693
msg.param.get_cmd(),
2694-
SystemMessage::MemberRemovedFromGroup | SystemMessage::SecurejoinMessage
2694+
SystemMessage::MemberRemovedFromGroup
2695+
| SystemMessage::SecurejoinMessage
2696+
| SystemMessage::WebxdcStatusUpdate
26952697
)
26962698
}
26972699
CantSendReason::MissingKey => msg
@@ -2701,7 +2703,7 @@ async fn prepare_send_msg(
27012703
_ => false,
27022704
};
27032705
if let Some(reason) = chat.why_cant_send_ex(context, &skip_fn).await? {
2704-
bail!("Cannot send to {chat_id}: {reason}");
2706+
bail!("Cannot prepare sending to {chat_id}: {reason}");
27052707
}
27062708

27072709
// Check a quote reply is not leaking data from other chats.

src/webxdc.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use serde_json::Value;
3434
use sha2::{Digest, Sha256};
3535
use tokio::{fs::File, io::BufReader};
3636

37-
use crate::chat::{self, Chat};
37+
use crate::chat::{self, CantSendReason, Chat};
3838
use crate::constants::Chattype;
3939
use crate::contact::ContactId;
4040
use crate::context::Context;
@@ -542,10 +542,16 @@ impl Context {
542542
let chat = Chat::load_from_db(self, chat_id)
543543
.await
544544
.with_context(|| format!("Failed to load chat {chat_id} from the database"))?;
545-
if let Some(reason) = chat.why_cant_send(self).await.with_context(|| {
546-
format!("Failed to check if webxdc update can be sent to chat {chat_id}")
547-
})? {
548-
bail!("Cannot send to {chat_id}: {reason}.");
545+
546+
let skip_fn = |reason: &CantSendReason| matches!(reason, CantSendReason::InBroadcast);
547+
if let Some(reason) = chat
548+
.why_cant_send_ex(self, &skip_fn)
549+
.await
550+
.with_context(|| {
551+
format!("Failed to check if webxdc update can be sent to chat {chat_id}")
552+
})?
553+
{
554+
bail!("Cannot send update to {chat_id}: {reason}.");
549555
}
550556

551557
let send_now = !matches!(

src/webxdc/webxdc_tests.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,3 +2235,91 @@ async fn test_webxdc_info_app_sender() -> Result<()> {
22352235

22362236
Ok(())
22372237
}
2238+
2239+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
2240+
async fn test_webxdc_broadcast_channel_updates() -> Result<()> {
2241+
let mut tcm = TestContextManager::new();
2242+
let alice = &tcm.alice().await;
2243+
let bob = &tcm.bob().await;
2244+
let charlie = &tcm.charlie().await;
2245+
2246+
// Alice creates a broadcast channel, Bob and Charlie join via securejoin QR
2247+
let alice_chat_id = create_broadcast(alice, "Channel".to_string()).await?;
2248+
let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await?;
2249+
tcm.exec_securejoin_qr(bob, alice, &qr).await;
2250+
tcm.exec_securejoin_qr(charlie, alice, &qr).await;
2251+
2252+
// Alice sends a webxdc app to the channel, Bob and Charlie both receive it
2253+
let alice_instance = send_webxdc_instance(alice, alice_chat_id).await?;
2254+
let sent1 = alice.pop_sent_msg().await;
2255+
2256+
let bob_instance = bob.recv_msg(&sent1).await;
2257+
assert_eq!(bob_instance.viewtype, Viewtype::Webxdc);
2258+
2259+
let charlie_instance = charlie.recv_msg(&sent1).await;
2260+
assert_eq!(charlie_instance.viewtype, Viewtype::Webxdc);
2261+
2262+
// Verify broadcast context flags
2263+
let alice_info = alice_instance.get_webxdc_info(alice).await?;
2264+
let bob_info = bob_instance.get_webxdc_info(bob).await?;
2265+
let charlie_info = charlie_instance.get_webxdc_info(charlie).await?;
2266+
assert!(alice_info.is_app_sender);
2267+
assert!(alice_info.is_broadcast);
2268+
assert!(!bob_info.is_app_sender);
2269+
assert!(bob_info.is_broadcast);
2270+
assert!(!charlie_info.is_app_sender);
2271+
assert!(charlie_info.is_broadcast);
2272+
2273+
// Alice sends a webxdc update, Bob and Charlie both receive it
2274+
alice
2275+
.send_webxdc_status_update(alice_instance.id, r#"{"payload": "hello from alice"}"#)
2276+
.await?;
2277+
alice.flush_status_updates().await?;
2278+
let sent2 = alice.pop_sent_msg().await;
2279+
2280+
bob.recv_msg_trash(&sent2).await;
2281+
assert_eq!(
2282+
bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0))
2283+
.await?,
2284+
r#"[{"payload":"hello from alice","serial":1,"max_serial":1}]"#
2285+
);
2286+
2287+
charlie.recv_msg_trash(&sent2).await;
2288+
assert_eq!(
2289+
charlie
2290+
.get_webxdc_status_updates(charlie_instance.id, StatusUpdateSerial(0))
2291+
.await?,
2292+
r#"[{"payload":"hello from alice","serial":1,"max_serial":1}]"#
2293+
);
2294+
2295+
// Bob sends a webxdc update, Bob sees ones own update, Alice receives it, but Charlie does not
2296+
bob.send_webxdc_status_update(bob_instance.id, r#"{"payload": "hello from bob"}"#)
2297+
.await?;
2298+
bob.flush_status_updates().await?;
2299+
let sent3 = bob.pop_sent_msg().await;
2300+
assert_eq!(
2301+
bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0))
2302+
.await?,
2303+
r#"[{"payload":"hello from alice","serial":1,"max_serial":2},
2304+
{"payload":"hello from bob","serial":2,"max_serial":2}]"#
2305+
);
2306+
2307+
alice.recv_msg_trash(&sent3).await;
2308+
assert_eq!(
2309+
alice
2310+
.get_webxdc_status_updates(alice_instance.id, StatusUpdateSerial(0))
2311+
.await?,
2312+
r#"[{"payload":"hello from alice","serial":1,"max_serial":2},
2313+
{"payload":"hello from bob","serial":2,"max_serial":2}]"#
2314+
);
2315+
2316+
charlie.recv_msg_trash(&sent3).await;
2317+
assert_eq!(
2318+
charlie
2319+
.get_webxdc_status_updates(charlie_instance.id, StatusUpdateSerial(0))
2320+
.await?,
2321+
r#"[{"payload":"hello from alice","serial":1,"max_serial":1}]"#
2322+
);
2323+
2324+
Ok(())
2325+
}

0 commit comments

Comments
 (0)