From ba83a4ba3d6886b711278b8804566dcbe8ad7621 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Fri, 6 Oct 2023 16:24:17 +0200 Subject: Calls: Correctly display information in partially encrypted calls This should never happen in practice, but now we will correctly display if a call has encrypted audio, but unencrypted video, or vice-versa. --- libdino/src/service/call_peer_state.vala | 6 +-- .../src/ui/call_window/call_encryption_button.vala | 52 ++++++++++++++++------ .../src/ui/call_window/call_window_controller.vala | 30 ++++++++----- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/libdino/src/service/call_peer_state.vala b/libdino/src/service/call_peer_state.vala index c7fa04da..3a005e01 100644 --- a/libdino/src/service/call_peer_state.vala +++ b/libdino/src/service/call_peer_state.vala @@ -9,7 +9,7 @@ public class Dino.PeerState : Object { public signal void connection_ready(); public signal void session_terminated(bool we_terminated, string? reason_name, string? reason_text); - public signal void encryption_updated(Xep.Jingle.ContentEncryption? audio_encryption, Xep.Jingle.ContentEncryption? video_encryption, bool same); + public signal void encryption_updated(Xep.Jingle.ContentEncryption? audio_encryption, Xep.Jingle.ContentEncryption? video_encryption); public StreamInteractor stream_interactor; public CallState call_state; @@ -412,7 +412,7 @@ public class Dino.PeerState : Object { if ((audio_encryptions != null && audio_encryptions.is_empty) || (video_encryptions != null && video_encryptions.is_empty)) { call.encryption = Encryption.NONE; - encryption_updated(null, null, true); + encryption_updated(null, null); return; } @@ -462,7 +462,7 @@ public class Dino.PeerState : Object { encryption_keys_same = true; } - encryption_updated(audio_encryption, video_encryption, encryption_keys_same); + encryption_updated(audio_encryption, video_encryption); } } diff --git a/main/src/ui/call_window/call_encryption_button.vala b/main/src/ui/call_window/call_encryption_button.vala index 1b586f28..4c417413 100644 --- a/main/src/ui/call_window/call_encryption_button.vala +++ b/main/src/ui/call_window/call_encryption_button.vala @@ -30,13 +30,32 @@ public class Dino.Ui.CallEncryptionButtonController : Object { update_opacity(); } - public void set_info(string? title, bool show_keys, Xmpp.Xep.Jingle.ContentEncryption? audio_encryption, Xmpp.Xep.Jingle.ContentEncryption? video_encryption) { + private static bool bytes_equal(uint8[] a1, uint8[] a2) { + return a1.length == a2.length && Memory.cmp(a1, a2, a1.length) == 0; + } + + private static bool encryption_equals(Xmpp.Xep.Jingle.ContentEncryption? audio_encryption, Xmpp.Xep.Jingle.ContentEncryption? video_encryption) { + if (audio_encryption == null && video_encryption == null) return true; + if (audio_encryption == null || video_encryption == null) return false; + if (audio_encryption.encryption_ns != video_encryption.encryption_ns) return false; + if (audio_encryption.encryption_name != video_encryption.encryption_name) return false; + if (!bytes_equal(audio_encryption.our_key,video_encryption.our_key)) return false; + if (!bytes_equal(audio_encryption.peer_key,video_encryption.peer_key)) return false; + return true; + } + + public void set_info(string? title, bool show_keys, bool has_audio, Xmpp.Xep.Jingle.ContentEncryption? audio_encryption, bool has_video, Xmpp.Xep.Jingle.ContentEncryption? video_encryption) { Popover popover = new Popover(); button.set_popover(popover); - if (audio_encryption == null) { - popover.set_child(new Label("This call is unencrypted.") ); - return; + Xmpp.Xep.Jingle.ContentEncryption? single_encryption = null; + if (!has_audio || !has_video || encryption_equals(audio_encryption, video_encryption)) { + single_encryption = audio_encryption ?? video_encryption; + + if (single_encryption == null) { + popover.set_child(new Label("This call is unencrypted.") ); + return; + } } if (title != null && !show_keys) { popover.set_child(new Label(title) { use_markup=true } ); @@ -44,15 +63,19 @@ public class Dino.Ui.CallEncryptionButtonController : Object { } Box box = new Box(Orientation.VERTICAL, 10); - box.append(new Label("%s".printf(title ?? "This call is end-to-end encrypted.")) { use_markup=true, xalign=0 }); - - if (video_encryption == null) { - box.append(create_media_encryption_grid(audio_encryption)); + if (single_encryption != null) { + box.append(new Label("%s".printf(title ?? "This call is end-to-end encrypted.")) { use_markup=true, xalign=0 }); + box.append(create_media_encryption_grid(single_encryption)); } else { - box.append(new Label("Audio") { use_markup=true, xalign=0 }); - box.append(create_media_encryption_grid(audio_encryption)); - box.append(new Label("Video") { use_markup=true, xalign=0 }); - box.append(create_media_encryption_grid(video_encryption)); + box.append(new Label("%s".printf(title ?? "This call is partially end-to-end encrypted.")) { use_markup=true, xalign=0 }); + if (has_audio) { + box.append(new Label("Audio") { use_markup=true, xalign=0 }); + box.append(create_media_encryption_grid(audio_encryption)); + } + if (has_video) { + box.append(new Label("Video") { use_markup=true, xalign=0 }); + box.append(create_media_encryption_grid(video_encryption)); + } } popover.set_child(box); } @@ -61,7 +84,10 @@ public class Dino.Ui.CallEncryptionButtonController : Object { button.opacity = controls_active && has_been_set ? 1 : 0; } - private Grid create_media_encryption_grid(Xmpp.Xep.Jingle.ContentEncryption? encryption) { + private Widget create_media_encryption_grid(Xmpp.Xep.Jingle.ContentEncryption? encryption) { + if (encryption == null) { + return new Label("This content is unencrypted.") { xalign=0 }; + } Grid ret = new Grid() { row_spacing=3, column_spacing=5 }; if (encryption.peer_key.length > 0) { ret.attach(new Label("Peer call key") { xalign=0 }, 1, 2, 1, 1); diff --git a/main/src/ui/call_window/call_window_controller.vala b/main/src/ui/call_window/call_window_controller.vala index 3fde9759..6e3eac6d 100644 --- a/main/src/ui/call_window/call_window_controller.vala +++ b/main/src/ui/call_window/call_window_controller.vala @@ -199,28 +199,34 @@ public class Dino.Ui.CallWindowController : Object { call_window.set_status(peer_id, "ringing"); } }); - peer_state.encryption_updated.connect((audio_encryption, video_encryption, same) => { - update_encryption_indicator(participant_widgets[peer_id].encryption_button_controller, audio_encryption, video_encryption, same); + peer_state.encryption_updated.connect((state, audio_encryption, video_encryption) => { + update_encryption_indicator(participant_widgets[peer_id].encryption_button_controller, peer_states[peer_id].audio_content != null, audio_encryption, peer_states[peer_id].video_content != null, video_encryption); }); } - private void update_encryption_indicator(CallEncryptionButtonController encryption_button, Xep.Jingle.ContentEncryption? audio_encryption, Xep.Jingle.ContentEncryption? video_encryption, bool same) { + private void update_encryption_indicator(CallEncryptionButtonController encryption_button, bool has_audio, Xep.Jingle.ContentEncryption? audio_encryption, bool has_video, Xep.Jingle.ContentEncryption? video_encryption) { string? title = null; string? icon_name = null; bool show_keys = true; Plugins.Registry registry = Dino.Application.get_default().plugin_registry; - Plugins.CallEncryptionEntry? encryption_entry = audio_encryption != null ? registry.call_encryption_entries[audio_encryption.encryption_ns] : null; - if (encryption_entry != null) { - Plugins.CallEncryptionWidget? encryption_widgets = encryption_entry.get_widget(call.account, audio_encryption); - if (encryption_widgets != null) { - title = encryption_widgets.get_title(); - icon_name = encryption_widgets.get_icon_name(); - show_keys = encryption_widgets.show_keys(); + if (((has_audio && audio_encryption != null) || (has_video && video_encryption != null)) && (!has_audio || !has_video || (audio_encryption != null && video_encryption != null && audio_encryption.encryption_ns == video_encryption.encryption_ns))) { + Plugins.CallEncryptionEntry? encryption_entry = audio_encryption != null ? registry.call_encryption_entries[audio_encryption.encryption_ns] : null; + if (encryption_entry != null) { + Plugins.CallEncryptionWidget? audio_encryption_widgets = encryption_entry.get_widget(call.account, audio_encryption); + Plugins.CallEncryptionWidget? video_encryption_widgets = encryption_entry.get_widget(call.account, video_encryption); + if (audio_encryption_widgets != null && video_encryption_widgets != null) { + if (audio_encryption_widgets.get_title() == video_encryption_widgets.get_title()) + title = audio_encryption_widgets.get_title(); + if (audio_encryption_widgets.get_icon_name() == video_encryption_widgets.get_icon_name()) + icon_name = audio_encryption_widgets.get_icon_name(); + if (audio_encryption_widgets.show_keys() == video_encryption_widgets.show_keys()) + show_keys = audio_encryption_widgets.show_keys(); + } } } - encryption_button.set_info(title, show_keys, audio_encryption, same ? null : video_encryption); - encryption_button.set_icon(audio_encryption != null, icon_name); + encryption_button.set_info(title, show_keys, has_audio, audio_encryption, has_video, video_encryption); + encryption_button.set_icon((!has_audio || audio_encryption != null) && (!has_video || video_encryption != null), icon_name); } private void add_new_participant(string participant_id, Jid jid) { -- cgit v1.2.3-54-g00ecf