diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 5de7d8deb..8b867f854 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4234,6 +4234,8 @@ char* dc_msg_get_webxdc_blob (const dc_msg_t* msg, const char* * true if the Webxdc should get internet access; * this is the case i.e. for experimental maps integration. * - self_addr: address to be used for `window.webxdc.selfAddr` in JS land. + * - is_app_sender: Define if the local user is the one who initially shared the webxdc application in the chat. + * - is_broadcast: Define if the app runs in a broadcasting context. * - send_update_interval: Milliseconds to wait before calling `sendUpdate()` again since the last call. * Should be exposed to `webxdc.sendUpdateInterval` in JS land. * - send_update_max_size: Maximum number of bytes accepted for a serialized update object. diff --git a/deltachat-jsonrpc/src/api/types/webxdc.rs b/deltachat-jsonrpc/src/api/types/webxdc.rs index 28d27a47a..aa8b3752a 100644 --- a/deltachat-jsonrpc/src/api/types/webxdc.rs +++ b/deltachat-jsonrpc/src/api/types/webxdc.rs @@ -37,6 +37,10 @@ pub struct WebxdcMessageInfo { internet_access: bool, /// Address to be used for `window.webxdc.selfAddr` in JS land. self_addr: String, + /// Define if the local user is the one who initially shared the webxdc application in the chat. + is_app_sender: bool, + /// Define if the app runs in a broadcasting context. + is_broadcast: bool, /// Milliseconds to wait before calling `sendUpdate()` again since the last call. /// Should be exposed to `window.sendUpdateInterval` in JS land. send_update_interval: usize, @@ -60,6 +64,8 @@ impl WebxdcMessageInfo { request_integration: _, internet_access, self_addr, + is_app_sender, + is_broadcast, send_update_interval, send_update_max_size, } = message.get_webxdc_info(context).await?; @@ -72,6 +78,8 @@ impl WebxdcMessageInfo { source_code_url: maybe_empty_string_to_option(source_code_url), internet_access, self_addr, + is_app_sender, + is_broadcast, send_update_interval, send_update_max_size, }) diff --git a/src/webxdc.rs b/src/webxdc.rs index 29184d23f..273ca5ca7 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -111,6 +111,12 @@ pub struct WebxdcInfo { /// Address to be used for `window.webxdc.selfAddr` in JS land. pub self_addr: String, + /// Define if the local user is the one who initially shared the webxdc application in the chat. + pub is_app_sender: bool, + + /// Define if the app runs in a broadcasting context. + pub is_broadcast: bool, + /// Milliseconds to wait before calling `sendUpdate()` again since the last call. /// Should be exposed to `window.sendUpdateInterval` in JS land. pub send_update_interval: usize, @@ -923,6 +929,11 @@ impl Message { let internet_access = is_integrated; let self_addr = self.get_webxdc_self_addr(context).await?; + let is_app_sender = self.from_id == ContactId::SELF; + let chat = Chat::load_from_db(context, self.chat_id) + .await + .with_context(|| "Failed to load chat from the database")?; + let is_broadcast = chat.typ == Chattype::InBroadcast || chat.typ == Chattype::OutBroadcast; Ok(WebxdcInfo { name: if let Some(name) = manifest.name { @@ -961,6 +972,8 @@ impl Message { request_integration, internet_access, self_addr, + is_app_sender, + is_broadcast, send_update_interval: context.ratelimit.read().await.update_interval(), send_update_max_size: RECOMMENDED_FILE_SIZE as usize, }) diff --git a/src/webxdc/webxdc_tests.rs b/src/webxdc/webxdc_tests.rs index 7590a0c33..85c38c851 100644 --- a/src/webxdc/webxdc_tests.rs +++ b/src/webxdc/webxdc_tests.rs @@ -12,6 +12,7 @@ use crate::chatlist::Chatlist; use crate::config::Config; use crate::ephemeral; use crate::receive_imf::receive_imf; +use crate::securejoin::get_securejoin_qr; use crate::test_utils::{E2EE_INFO_MSGS, TestContext, TestContextManager}; use crate::tools::{self, SystemTime}; use crate::{message, sql}; @@ -2195,3 +2196,42 @@ async fn test_self_addr_consistency() -> Result<()> { assert_eq!(db_msg.get_webxdc_self_addr(alice).await?, self_addr); Ok(()) } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_webxdc_info_app_sender() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + + // Alice sends webxdc in a group chat + let alice_chat_id = alice.create_group_with_members("Group", &[bob]).await; + let alice_instance = send_webxdc_instance(alice, alice_chat_id).await?; + let sent1 = alice.pop_sent_msg().await; + let alice_info = alice_instance.get_webxdc_info(alice).await?; + assert!(alice_info.is_app_sender); + assert!(!alice_info.is_broadcast); + + // Bob receives group webxdc + let bob_instance = bob.recv_msg(&sent1).await; + let bob_info = bob_instance.get_webxdc_info(bob).await?; + assert!(!bob_info.is_app_sender); + assert!(!bob_info.is_broadcast); + + // Alice sends webxdc to broadcast channel + let alice_chat_id = create_broadcast(alice, "Broadcast".to_string()).await?; + let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await.unwrap(); + tcm.exec_securejoin_qr(bob, alice, &qr).await; + let alice_instance = send_webxdc_instance(alice, alice_chat_id).await?; + let sent2 = alice.pop_sent_msg().await; + let alice_info = alice_instance.get_webxdc_info(alice).await?; + assert!(alice_info.is_app_sender); + assert!(alice_info.is_broadcast); + + // Bob receives broadcast webxdc + let bob_instance = bob.recv_msg(&sent2).await; + let bob_info = bob_instance.get_webxdc_info(bob).await?; + assert!(!bob_info.is_app_sender); + assert!(bob_info.is_broadcast); + + Ok(()) +}