Skip to content

Commit 996877e

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

3 files changed

Lines changed: 100 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: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,3 +2235,88 @@ 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 claire = &tcm.charlie().await;
2245+
2246+
// Alice creates a broadcast channel
2247+
let alice_broadcast_id = create_broadcast(alice, "Channel".to_string()).await?;
2248+
2249+
// Bob and Claire join via securejoin QR
2250+
let qr = get_securejoin_qr(alice, Some(alice_broadcast_id)).await?;
2251+
tcm.exec_securejoin_qr(bob, alice, &qr).await;
2252+
let qr = get_securejoin_qr(alice, Some(alice_broadcast_id)).await?;
2253+
tcm.exec_securejoin_qr(claire, alice, &qr).await;
2254+
2255+
// Alice sends a webxdc app to the channel
2256+
let alice_instance = send_webxdc_instance(alice, alice_broadcast_id).await?;
2257+
let sent_instance = alice.pop_sent_msg().await;
2258+
2259+
// Bob and Claire receive the webxdc app
2260+
let bob_instance = bob.recv_msg(&sent_instance).await;
2261+
let claire_instance = claire.recv_msg(&sent_instance).await;
2262+
assert_eq!(bob_instance.viewtype, Viewtype::Webxdc);
2263+
assert_eq!(claire_instance.viewtype, Viewtype::Webxdc);
2264+
2265+
// Verify broadcast context flags
2266+
assert!(alice_instance.get_webxdc_info(alice).await?.is_app_sender);
2267+
assert!(alice_instance.get_webxdc_info(alice).await?.is_broadcast);
2268+
assert!(!bob_instance.get_webxdc_info(bob).await?.is_app_sender);
2269+
assert!(bob_instance.get_webxdc_info(bob).await?.is_broadcast);
2270+
assert!(!claire_instance.get_webxdc_info(claire).await?.is_app_sender);
2271+
assert!(claire_instance.get_webxdc_info(claire).await?.is_broadcast);
2272+
2273+
// Alice sends a webxdc update, Bob and Claire 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 sent_alice_update = alice.pop_sent_msg().await;
2279+
2280+
bob.recv_msg_trash(&sent_alice_update).await;
2281+
claire.recv_msg_trash(&sent_alice_update).await;
2282+
2283+
assert_eq!(
2284+
bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0))
2285+
.await?,
2286+
r#"[{"payload":"hello from alice","serial":1,"max_serial":1}]"#
2287+
);
2288+
assert_eq!(
2289+
claire
2290+
.get_webxdc_status_updates(claire_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 — Alice should receive it, but Claire should NOT
2296+
bob.send_webxdc_status_update(bob_instance.id, r#"{"payload": "hello from bob"}"#)
2297+
.await?;
2298+
bob.flush_status_updates().await?;
2299+
2300+
let sent_bob_update = bob.pop_sent_msg().await;
2301+
2302+
// Alice receives Bob's update
2303+
alice.recv_msg_trash(&sent_bob_update).await;
2304+
assert_eq!(
2305+
alice
2306+
.get_webxdc_status_updates(alice_instance.id, StatusUpdateSerial(0))
2307+
.await?,
2308+
r#"[{"payload":"hello from alice","serial":1,"max_serial":2},
2309+
{"payload":"hello from bob","serial":2,"max_serial":2}]"#
2310+
);
2311+
2312+
// Claire does NOT receive Bob's update;
2313+
// in a broadcast channel, subscriber updates are sent back to the owner only
2314+
assert_eq!(
2315+
claire
2316+
.get_webxdc_status_updates(claire_instance.id, StatusUpdateSerial(0))
2317+
.await?,
2318+
r#"[{"payload":"hello from alice","serial":1,"max_serial":1}]"#
2319+
);
2320+
2321+
Ok(())
2322+
}

0 commit comments

Comments
 (0)