From 0940c88c20d469e847935fa1e19fc399d5275e34 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 28 Sep 2023 09:04:03 -0400 Subject: [PATCH] CallLink NullMessage sending. --- .../securesms/WebRtcCallActivity.java | 6 ++ .../webrtc/CallLinkNullMessageSender.kt | 56 +++++++++++++++++++ .../CallLinkConnectedActionProcessor.kt | 3 + 3 files changed, 65 insertions(+) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallLinkNullMessageSender.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java index 43023e29d1..672cd6d497 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java @@ -58,6 +58,7 @@ import org.signal.libsignal.protocol.IdentityKey; import org.thoughtcrime.securesms.components.TooltipPopup; import org.thoughtcrime.securesms.components.sensors.DeviceOrientationMonitor; import org.thoughtcrime.securesms.components.webrtc.CallLinkInfoSheet; +import org.thoughtcrime.securesms.components.webrtc.CallLinkNullMessageSender; import org.thoughtcrime.securesms.components.webrtc.CallParticipantsListUpdatePopupWindow; import org.thoughtcrime.securesms.components.webrtc.CallParticipantsState; import org.thoughtcrime.securesms.components.webrtc.CallStateUpdatePopupWindow; @@ -99,6 +100,7 @@ import org.thoughtcrime.securesms.webrtc.CallParticipantsViewState; import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager; import org.whispersystems.signalservice.api.messages.calls.HangupMessage; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -775,6 +777,10 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan return; } + if (state.isCallLink()) { + CallLinkNullMessageSender.onSendAnyway(new HashSet<>(changedRecipients)); + } + if (state.getGroupCallState().isConnected()) { ApplicationDependencies.getSignalCallManager().groupApproveSafetyChange(changedRecipients); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallLinkNullMessageSender.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallLinkNullMessageSender.kt new file mode 100644 index 0000000000..d7f0081c6c --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallLinkNullMessageSender.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.components.webrtc + +import org.thoughtcrime.securesms.database.identity.IdentityRecordList +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import org.thoughtcrime.securesms.jobs.NullMessageSendJob +import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.recipients.RecipientId + +/** + * In-Memory Cache that keeps track of whom we've sent NullMessages to. This is + * something that really only needs to happen once so that profile information is + * displayed correctly, so we maintain an application process scoped cache. + */ +object CallLinkNullMessageSender { + private val cache = hashSetOf() + + /** + * Invoked after pressing "Join" or "Continue" on the safety number change dialog before + * or during a call. + */ + @JvmStatic + fun onSendAnyway(recipientIds: Set) { + val toSendMessagesTo: Set = recipientIds - cache + cache += recipientIds + + val jobs: List = toSendMessagesTo.map { NullMessageSendJob(it) } + ApplicationDependencies.getJobManager().addAll(jobs) + } + + /** + * Given the set of recipients, for each unblocked recipient we don't distrust, send a NullMessage + */ + fun onRecipientsUpdated(recipients: Set) { + val nonBlockedRecipients: List = recipients.filterNot { it.isBlocked } + + val identityRecords: IdentityRecordList = ApplicationDependencies + .getProtocolStore() + .aci() + .identities() + .getIdentityRecords(nonBlockedRecipients) + + val untrustedAndUnverifiedRecipients = if (identityRecords.isUntrusted(false) || identityRecords.isUnverified(false)) { + (identityRecords.untrustedRecipients + identityRecords.unverifiedRecipients).toSet() + } else { + emptySet() + } + + val trustedRecipients: Set = (nonBlockedRecipients - untrustedAndUnverifiedRecipients).map { it.id }.toSet() + onSendAnyway(trustedRecipients) + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkConnectedActionProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkConnectedActionProcessor.kt index d13c4ad8d1..a63082582f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkConnectedActionProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkConnectedActionProcessor.kt @@ -9,6 +9,7 @@ import org.signal.core.util.logging.Log import org.signal.ringrtc.CallException import org.signal.ringrtc.GroupCall import org.signal.ringrtc.PeekInfo +import org.thoughtcrime.securesms.components.webrtc.CallLinkNullMessageSender import org.thoughtcrime.securesms.database.CallLinkTable import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.events.CallParticipant @@ -54,6 +55,8 @@ class CallLinkConnectedActionProcessor( Log.i(tag, "Updating pending list with ${peekInfo.pendingUsers.size} entries.") val pendingParticipants: List = peekInfo.pendingUsers.map { Recipient.externalPush(ServiceId.ACI.from(it)) } + CallLinkNullMessageSender.onRecipientsUpdated(superState.callInfoState.remoteCallParticipants.map { it.recipient }.toSet()) + return superState.builder() .changeCallInfoState() .setCallLinkPendingParticipants(pendingParticipants)