diff --git a/bindings/matrix-sdk-ffi/src/widget.rs b/bindings/matrix-sdk-ffi/src/widget.rs index 77fcc1c29..33c3f2378 100644 --- a/bindings/matrix-sdk-ffi/src/widget.rs +++ b/bindings/matrix-sdk-ffi/src/widget.rs @@ -248,6 +248,11 @@ pub struct VirtualElementCallWidgetOptions { /// Sentry [environment](https://docs.sentry.io/concepts/key-terms/key-terms/) /// Supported since Element Call v0.9.0. Only used by the embedded package. pub sentry_environment: Option, + //// - `true`: The webview should show the list of media devices it detects using + //// `enumerateDevices`. + /// - `false`: the webview shows a a list of devices injected by the + /// client. (used on ios & android) + pub controlled_media_devices: bool, } impl From for matrix_sdk::widget::VirtualElementCallWidgetOptions { @@ -271,6 +276,7 @@ impl From for matrix_sdk::widget::VirtualElemen rageshake_submit_url: value.rageshake_submit_url, sentry_dsn: value.sentry_dsn, sentry_environment: value.sentry_environment, + controlled_media_devices: value.controlled_media_devices, } } } diff --git a/crates/matrix-sdk/src/widget/settings/element_call.rs b/crates/matrix-sdk/src/widget/settings/element_call.rs index 5fa89b00c..4603e1746 100644 --- a/crates/matrix-sdk/src/widget/settings/element_call.rs +++ b/crates/matrix-sdk/src/widget/settings/element_call.rs @@ -70,6 +70,7 @@ struct ElementCallParams { /// Supported since Element Call v0.9.0. Only used by the embedded package. sentry_environment: Option, hide_screensharing: bool, + controlled_media_devices: bool, } /// Defines if a call is encrypted and which encryption system should be used. @@ -193,6 +194,11 @@ pub struct VirtualElementCallWidgetOptions { /// Sentry [environment](https://docs.sentry.io/concepts/key-terms/key-terms/) /// This is only used by the embedded package of Element Call. pub sentry_environment: Option, + //// - `true`: The webview should show the list of media devices it detects using + //// `enumerateDevices`. + /// - `false`: the webview shows a a list of devices injected by the + /// client. (used on ios & android) + pub controlled_media_devices: bool, } impl WidgetSettings { @@ -253,6 +259,7 @@ impl WidgetSettings { sentry_environment: props.sentry_environment, rageshake_submit_url: props.rageshake_submit_url, hide_screensharing: props.hide_screensharing, + controlled_media_devices: props.controlled_media_devices, }; let query = @@ -288,6 +295,7 @@ mod tests { rageshake: bool, sentry: bool, intent: Option, + controlle_output: bool, ) -> WidgetSettings { let mut props = VirtualElementCallWidgetOptions { element_call_url: "https://call.element.io".to_owned(), @@ -298,6 +306,7 @@ mod tests { confine_to_room: Some(true), encryption: encryption.unwrap_or(EncryptionSystem::PerParticipantKeys), intent, + controlled_media_devices: controlle_output, ..VirtualElementCallWidgetOptions::default() }; @@ -345,13 +354,13 @@ mod tests { } #[test] - fn new_virtual_element_call_widget_base_url() { - let widget_settings = get_widget_settings(None, false, false, false, None); + fn test_new_virtual_element_call_widget_base_url() { + let widget_settings = get_widget_settings(None, false, false, false, None, false); assert_eq!(widget_settings.base_url().unwrap().as_str(), "https://call.element.io/"); } #[test] - fn new_virtual_element_call_widget_raw_url() { + fn test_new_virtual_element_call_widget_raw_url() { const CONVERTED_URL: &str = " https://call.element.io#\ ?userId=$matrix_user_id\ @@ -370,9 +379,10 @@ mod tests { &preload=true\ &perParticipantE2EE=true\ &hideScreensharing=false\ + &controlledMediaDevices=false\ "; - let mut url = get_widget_settings(None, false, false, false, None).raw_url().clone(); + let mut url = get_widget_settings(None, false, false, false, None, false).raw_url().clone(); let mut gen = Url::parse(CONVERTED_URL).unwrap(); assert_eq!(get_query_sets(&url).unwrap(), get_query_sets(&gen).unwrap()); url.set_fragment(None); @@ -383,8 +393,11 @@ mod tests { } #[test] - fn new_virtual_element_call_widget_id() { - assert_eq!(get_widget_settings(None, false, false, false, None).widget_id(), WIDGET_ID); + fn test_new_virtual_element_call_widget_id() { + assert_eq!( + get_widget_settings(None, false, false, false, None, false).widget_id(), + WIDGET_ID + ); } fn build_url_from_widget_settings(settings: WidgetSettings) -> String { @@ -406,7 +419,7 @@ mod tests { } #[test] - fn new_virtual_element_call_widget_webview_url() { + fn test_new_virtual_element_call_widget_webview_url() { const CONVERTED_URL: &str = " https://call.element.io#\ ?parentUrl=https%3A%2F%2Fcall.element.io\ @@ -423,9 +436,11 @@ mod tests { &clientId=io.my_matrix.client\ &perParticipantE2EE=true\ &hideScreensharing=false\ + &controlledMediaDevices=false\ "; - let gen = - build_url_from_widget_settings(get_widget_settings(None, false, false, false, None)); + let gen = build_url_from_widget_settings(get_widget_settings( + None, false, false, false, None, false, + )); let mut url = Url::parse(&gen).unwrap(); let mut gen = Url::parse(CONVERTED_URL).unwrap(); @@ -438,7 +453,7 @@ mod tests { } #[test] - fn new_virtual_element_call_widget_webview_url_with_posthog_rageshake_sentry() { + fn test_new_virtual_element_call_widget_webview_url_with_posthog_rageshake_sentry() { const CONVERTED_URL: &str = " https://call.element.io#\ ?parentUrl=https%3A%2F%2Fcall.element.io\ @@ -462,8 +477,11 @@ mod tests { &rageshakeSubmitUrl=https%3A%2F%2Frageshake.element.io\ &sentryDsn=SENTRY_DSN\ &sentryEnvironment=SENTRY_ENV\ + &controlledMediaDevices=false\ "; - let gen = build_url_from_widget_settings(get_widget_settings(None, true, true, true, None)); + let gen = build_url_from_widget_settings(get_widget_settings( + None, true, true, true, None, false, + )); let mut url = Url::parse(&gen).unwrap(); let mut gen = Url::parse(CONVERTED_URL).unwrap(); @@ -476,7 +494,7 @@ mod tests { } #[test] - fn password_url_props_from_widget_settings() { + fn test_password_url_props_from_widget_settings() { { // PerParticipantKeys let url = build_url_from_widget_settings(get_widget_settings( @@ -485,6 +503,7 @@ mod tests { false, false, None, + false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; let expected_elements = [("perParticipantE2EE".to_owned(), "true".to_owned())]; @@ -505,6 +524,7 @@ mod tests { false, false, None, + false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; let expected_elements = ("perParticipantE2EE".to_owned(), "false".to_owned()); @@ -523,6 +543,7 @@ mod tests { false, false, None, + false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; let expected_elements = [("password".to_owned(), "this_surely_is_save".to_owned())]; @@ -538,11 +559,34 @@ mod tests { } #[test] - fn intent_url_props_from_widget_settings() { + fn test_controlled_output_url_props_from_widget_settings() { + { + // PerParticipantKeys + let url = build_url_from_widget_settings(get_widget_settings( + Some(EncryptionSystem::PerParticipantKeys), + false, + false, + false, + None, + true, + )); + let controlled_media_element = ("controlledMediaDevices".to_owned(), "true".to_owned()); + let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; + assert!( + query_set.contains(&controlled_media_element), + "The query elements: \n{:?}\nDid not contain: \n{:?}", + query_set, + controlled_media_element + ); + } + } + + #[test] + fn test_intent_url_props_from_widget_settings() { { // no intent let url = build_url_from_widget_settings(get_widget_settings( - None, false, false, false, None, + None, false, false, false, None, false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; @@ -565,6 +609,7 @@ mod tests { false, false, Some(Intent::JoinExisting), + false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1; let expected_elements = ("intent".to_owned(), "join_existing".to_owned()); @@ -594,6 +639,7 @@ mod tests { false, false, Some(Intent::StartCall), + false, )); let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;