Skip to content

Commit

Permalink
feat: App soft lock when E2EI is required (WPB-5876) (#2563)
Browse files Browse the repository at this point in the history
  • Loading branch information
borichellow authored Jan 9, 2024
1 parent e82429b commit c11b6b5
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.feature.message.MarkMessagesAsNotifiedUseCase
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.feature.session.GetAllSessionsResult
import com.wire.kalium.logic.feature.user.E2EIRequiredResult
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -51,6 +52,7 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
Expand Down Expand Up @@ -303,9 +305,17 @@ class WireNotificationManager @Inject constructor(
) {
appLogger.d("$TAG observe incoming calls")

coreLogic.getSessionScope(userId)
.calls
.getIncomingCalls()
coreLogic.getSessionScope(userId).observeE2EIRequired()
.map { it is E2EIRequiredResult.NoGracePeriod }
.distinctUntilChanged()
.flatMapLatest { isBlockedByE2EIRequired ->
if (isBlockedByE2EIRequired) {
appLogger.d("$TAG calls were blocked as E2EI is required")
flowOf(listOf())
} else {
coreLogic.getSessionScope(userId).calls.getIncomingCalls()
}
}
.collect { calls ->
callNotificationManager.handleIncomingCallNotifications(calls, userId)
}
Expand All @@ -329,33 +339,37 @@ class WireNotificationManager @Inject constructor(
.distinctUntilChanged()
.stateIn(scope)

val isBlockedByE2EIRequiredState = coreLogic.getSessionScope(userId).observeE2EIRequired()
.map { it is E2EIRequiredResult.NoGracePeriod }
.distinctUntilChanged()
.stateIn(scope)

coreLogic.getSessionScope(userId)
.messages
.getNotifications()
.cancellable()
.onEach { newNotifications ->
playPingSoundIfNeeded(
currentScreen = currentScreenState.value,
notifications = newNotifications
)
}
.map { newNotifications ->
// we don't want to display notifications for the Conversation that user currently in.
val notificationsList = filterAccordingToScreenAndUpdateNotifyDate(
filterAccordingToScreenAndUpdateNotifyDate(
currentScreenState.value,
userId,
newNotifications
)

playPingSoundIfNeeded(
currentScreen = currentScreenState.value,
notifications = newNotifications
)
val userName = selfUserNameState.value

// combining all the data that is necessary for Notifications into small data class,
// just to make it more readable than
// Triple<List<LocalNotification>, QualifiedID, String>
MessagesNotificationsData(notificationsList, userId, userName)
}
.cancellable()
.collect { (newNotifications, userId, userName) ->
.collect { newNotifications ->
appLogger.d("$TAG got ${newNotifications.size} notifications")
messagesNotificationManager.handleNotification(newNotifications, userId, userName)
if (isBlockedByE2EIRequiredState.value) {
appLogger.d("$TAG notifications were skipped as E2EI is required")
} else {
messagesNotificationManager.handleNotification(newNotifications, userId, selfUserNameState.value)
}
markMessagesAsNotified(userId)
markConnectionAsNotified(userId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ import com.wire.kalium.logic.feature.session.CurrentSessionFlowUseCase
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.feature.session.GetAllSessionsResult
import com.wire.kalium.logic.feature.session.GetSessionsUseCase
import com.wire.kalium.logic.feature.user.E2EIRequiredResult
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.feature.user.ObserveE2EIRequiredUseCase
import com.wire.kalium.logic.feature.user.UserScope
import com.wire.kalium.logic.sync.SyncManager
import io.mockk.MockKAnnotations
Expand Down Expand Up @@ -664,6 +666,36 @@ class WireNotificationManagerTest {
verify(exactly = 1) { arrangement.servicesManager.stopOngoingCallService() }
}

@Test
fun givenSomeNotificationsAndUserBlockedByE2EIRequired_whenObserveCalled_thenNotificationIsNotShowed() =
runTestWithCancellation(dispatcherProvider.main()) {
val conversationId = ConversationId("conversation_value", "conversation_domain")
val (arrangement, manager) = Arrangement()
.withMessageNotifications(
listOf(
provideLocalNotificationConversation(
id = conversationId,
messages = listOf(provideLocalNotificationMessage())
)
)
).withIncomingCalls(listOf())
.withCurrentScreen(CurrentScreen.SomeOther)
.withObserveE2EIRequired(E2EIRequiredResult.NoGracePeriod.Create)
.arrange()

manager.observeNotificationsAndCallsWhileRunning(listOf(provideUserId(TestUser.SELF_USER.id.value)), this)
runCurrent()

verify(exactly = 0) {
arrangement.messageNotificationManager.handleNotification(
listOf(), TestUser.SELF_USER.id, TestUser.SELF_USER.handle!!
)
}
coVerify(atLeast = 1) {
arrangement.markMessagesAsNotified(MarkMessagesAsNotifiedUseCase.UpdateTarget.AllConversations)
}
}

private inner class Arrangement {
@MockK
lateinit var coreLogic: CoreLogic
Expand Down Expand Up @@ -731,6 +763,9 @@ class WireNotificationManagerTest {
@MockK
lateinit var pingRinger: PingRinger

@MockK
lateinit var observeE2EIRequired: ObserveE2EIRequiredUseCase

private val currentSessionChannel = Channel<CurrentSessionResult>(capacity = Channel.UNLIMITED)

val wireNotificationManager by lazy {
Expand All @@ -749,11 +784,13 @@ class WireNotificationManagerTest {
init {
MockKAnnotations.init(this, relaxUnitFun = true)

coEvery { observeE2EIRequired() } returns flowOf(E2EIRequiredResult.NotRequired)
coEvery { userSessionScope.calls } returns callsScope
coEvery { userSessionScope.messages } returns messageScope
coEvery { userSessionScope.syncManager } returns syncManager
coEvery { userSessionScope.conversations } returns conversationScope
coEvery { userSessionScope.users } returns userScope
coEvery { userSessionScope.observeE2EIRequired } returns observeE2EIRequired
coEvery { conversationScope.markConnectionRequestAsNotified } returns markConnectionRequestAsNotified
coEvery { userScope.getSelfUser } returns getSelfUser
coEvery { markConnectionRequestAsNotified(any()) } returns Unit
Expand Down Expand Up @@ -801,6 +838,7 @@ class WireNotificationManagerTest {
coEvery { users } returns mockk {
coEvery { getSelfUser() } returns flowOf(selfUser)
}
coEvery { observeE2EIRequired } returns this@Arrangement.observeE2EIRequired
}
}

Expand Down Expand Up @@ -848,6 +886,10 @@ class WireNotificationManagerTest {
coEvery { getSelfUser.invoke() } returns selfUserFlow
}

fun withObserveE2EIRequired(result: E2EIRequiredResult) = apply {
coEvery { observeE2EIRequired.invoke() } returns flowOf(result)
}

fun arrange() = this to wireNotificationManager
}

Expand Down

0 comments on commit c11b6b5

Please sign in to comment.