diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt index 00c6187549b..8988006e512 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt @@ -455,6 +455,10 @@ class CallActivity : CallBaseActivity() { processExtras(intent.extras!!) conversationUser = currentUserProviderOld.currentUser.blockingGet() + if (warnAndFinishIfCallEndToEndEncryptionUnsupported()) { + return + } + credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser!!.token) if (TextUtils.isEmpty(baseUrl)) { baseUrl = conversationUser!!.baseUrl @@ -477,6 +481,15 @@ class CallActivity : CallBaseActivity() { checkInitialDevicePermissions() } + private fun warnAndFinishIfCallEndToEndEncryptionUnsupported(): Boolean { + if (!CapabilitiesUtil.isCallEndToEndEncryptionEnabled(conversationUser?.capabilities?.spreedCapability)) { + return false + } + Toast.makeText(context, R.string.nc_call_e2ee_not_supported, Toast.LENGTH_LONG).show() + finish() + return true + } + private fun initCallRecordingViewModel(recordingState: Int) { callRecordingViewModel = ViewModelProvider(this, viewModelFactory).get( CallRecordingViewModel::class.java diff --git a/app/src/main/java/com/nextcloud/talk/callnotification/CallNotificationActivity.kt b/app/src/main/java/com/nextcloud/talk/callnotification/CallNotificationActivity.kt index aaad05b3aef..abcd3d9d022 100644 --- a/app/src/main/java/com/nextcloud/talk/callnotification/CallNotificationActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/callnotification/CallNotificationActivity.kt @@ -15,6 +15,7 @@ import android.os.Handler import android.os.Looper import android.util.Log import android.view.View +import android.widget.Toast import androidx.core.app.NotificationManagerCompat import autodagger.AutoInjector import com.nextcloud.talk.R @@ -29,6 +30,7 @@ import com.nextcloud.talk.extensions.loadUserAvatar import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.CapabilitiesUtil import com.nextcloud.talk.utils.CapabilitiesUtil.hasSpreedFeatureCapability import com.nextcloud.talk.utils.NotificationUtils import com.nextcloud.talk.utils.SpreedFeatures @@ -190,6 +192,11 @@ class CallNotificationActivity : CallBaseActivity() { } private fun proceedToCall() { + if (CapabilitiesUtil.isCallEndToEndEncryptionEnabled(userBeingCalled?.capabilities?.spreedCapability)) { + Toast.makeText(context, R.string.nc_call_e2ee_not_supported, Toast.LENGTH_LONG).show() + hangup() + return + } val callIntent = Intent(this, CallActivity::class.java) intent.putExtra(KEY_ROOM_ONE_TO_ONE, isOneToOneCall) callIntent.putExtras(intent.extras!!) diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 0b174c37857..71a21eaaa15 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -3437,6 +3437,10 @@ class ChatActivity : private fun startACall(isVoiceOnlyCall: Boolean, callWithoutNotification: Boolean) { currentConversation?.let { if (::conversationUser.isInitialized) { + if (CapabilitiesUtil.isCallEndToEndEncryptionEnabled(spreedCapabilities)) { + Snackbar.make(binding.root, R.string.nc_call_e2ee_not_supported, Snackbar.LENGTH_LONG).show() + return + } val pp = ParticipantPermissions(spreedCapabilities, it) if (!pp.canStartCall() && currentConversation?.hasCall == false) { Snackbar.make(binding.root, R.string.startCallForbidden, Snackbar.LENGTH_LONG).show() diff --git a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt index 51dc3d0c75c..220b95633a1 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt @@ -37,7 +37,6 @@ import android.widget.RelativeLayout import android.widget.SeekBar import androidx.appcompat.view.ContextThemeWrapper import androidx.compose.material3.MaterialTheme -import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toDrawable import androidx.core.view.isVisible import androidx.core.widget.doAfterTextChanged diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt index 059bba60338..006ebcf55e9 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt @@ -1100,6 +1100,10 @@ class ConversationsListActivity : BaseActivity() { chatIntent.putExtras(bundle) if (currentUser != null) { + if (CapabilitiesUtil.isCallEndToEndEncryptionEnabled(currentUser?.capabilities?.spreedCapability)) { + showSnackbar(context.getString(R.string.nc_call_e2ee_not_supported)) + return@let + } val pp = ParticipantPermissions(currentUser?.capabilities?.spreedCapability, it) if (!pp.canStartCall() && selectedConversation?.hasCall == false) { Log.e(TAG, "Error starting call from conversations list: call is forbidden") diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt index 86cb13d8388..4358cf0d83d 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt +++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt @@ -76,6 +76,7 @@ import com.nextcloud.talk.receivers.ShareRecordingToChatReceiver import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ActorAvatar import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.CapabilitiesUtil import com.nextcloud.talk.utils.CharacterAvatarUtils import com.nextcloud.talk.utils.ConversationUtils import com.nextcloud.talk.utils.DisplayUtils @@ -404,7 +405,14 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor override fun onNext(conversation: ConversationModel) { if (userManager.setUserAsActive(userBeingCalled!!).blockingGet()) { - prepareCallNotificationScreen(conversation) + if (CapabilitiesUtil.isCallEndToEndEncryptionEnabled( + userBeingCalled?.capabilities?.spreedCapability + ) + ) { + showEndToEndEncryptionUnsupportedNotification(conversation) + } else { + prepareCallNotificationScreen(conversation) + } } } @@ -1299,6 +1307,34 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor } } + private fun showEndToEndEncryptionUnsupportedNotification(conversation: ConversationModel) { + val notificationBuilder = NotificationCompat.Builder( + context!!, + NotificationUtils.NotificationChannels + .NOTIFICATION_CHANNEL_MESSAGES_V4.name + ) + + val intent = createMainActivityIntent() + + val notification: Notification = notificationBuilder + .setContentTitle( + String.format( + context!!.resources.getString(R.string.nc_call_e2ee_not_supported_title), + conversation.displayName + ) + ) + .setContentText(context!!.resources.getString(R.string.nc_call_e2ee_not_supported)) + .setSmallIcon(R.drawable.ic_call_black_24dp) + .setOngoing(false) + .setAutoCancel(true) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setContentIntent(createUniquePendingIntent(intent)) + .build() + + sendNotification(pushMessage.timestamp.toInt(), notification) + Log.d(TAG, "'end-to-end-encryption not supported' notification was created for ${conversation.token}") + } + private fun createMainActivityIntent(): Intent { val intent = Intent(context, MainActivity::class.java) intent.flags = getIntentFlags() diff --git a/app/src/main/java/com/nextcloud/talk/utils/CapabilitiesUtil.kt b/app/src/main/java/com/nextcloud/talk/utils/CapabilitiesUtil.kt index 5448fbed8dc..04ab84f0359 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/CapabilitiesUtil.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/CapabilitiesUtil.kt @@ -327,6 +327,17 @@ object CapabilitiesUtil { fun isBanningAvailable(spreedCapabilities: SpreedCapability): Boolean = hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.BAN_V1) + fun isCallEndToEndEncryptionEnabled(spreedCapabilities: SpreedCapability?): Boolean { + if ( + spreedCapabilities?.config?.containsKey("call") == true && + spreedCapabilities.config!!["call"] != null && + spreedCapabilities.config!!["call"]!!.containsKey("end-to-end-encryption") + ) { + return spreedCapabilities.config!!["call"]!!["end-to-end-encryption"].toString().toBoolean() + } + return false + } + // endregion //region SpreedCapabilities that can't be used with federation as the settings for them are global diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9daacee5f3e..85b4dadbfbc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -641,6 +641,8 @@ How to translate with transifex: Keep Message deleted successfully, but it might have been leaked to other services You are not allowed to start a call + Call from %s unavailable + Calling is currently not supported because end-to-end encryption is enabled on the server You need to promote a new moderator before you can leave the conversation Room is retained successfully