mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Verification with QrCode: ensure there is a Camera to scan QrCodes.
This commit is contained in:
parent
9f28738fd6
commit
a914381090
7 changed files with 134 additions and 56 deletions
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package im.vector.riotx.core.hardware
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.Camera
|
||||
import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.os.Build
|
||||
import javax.inject.Inject
|
||||
|
||||
class HardwareInfo @Inject constructor(
|
||||
private val context: Context
|
||||
) {
|
||||
/**
|
||||
* Tell if the device has a back (or external) camera
|
||||
*/
|
||||
fun hasBackCamera(): Boolean {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return Camera.getNumberOfCameras() > 0
|
||||
}
|
||||
|
||||
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager? ?: return Camera.getNumberOfCameras() > 0
|
||||
|
||||
return manager.cameraIdList.any {
|
||||
val lensFacing = manager.getCameraCharacteristics(it).get(CameraCharacteristics.LENS_FACING)
|
||||
lensFacing == CameraCharacteristics.LENS_FACING_BACK || lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.crypto.verification
|
||||
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
||||
|
||||
val supportedVerificationMethods =
|
||||
listOf(
|
||||
// RiotX supports SAS verification
|
||||
VerificationMethod.SAS,
|
||||
// RiotX is able to show QR codes
|
||||
VerificationMethod.QR_CODE_SHOW,
|
||||
// RiotX is able to scan QR codes
|
||||
VerificationMethod.QR_CODE_SCAN
|
||||
)
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.crypto.verification
|
||||
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
||||
import im.vector.riotx.core.hardware.HardwareInfo
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class SupportedVerificationMethodsProvider @Inject constructor(
|
||||
private val hardwareInfo: HardwareInfo
|
||||
) {
|
||||
/**
|
||||
* Provide the list of supported method by RiotX, with or without the QR_CODE_SCAN, depending if a back camera
|
||||
* is available
|
||||
*/
|
||||
fun provide(): List<VerificationMethod> {
|
||||
return mutableListOf(
|
||||
// RiotX supports SAS verification
|
||||
VerificationMethod.SAS,
|
||||
// RiotX is able to show QR codes
|
||||
VerificationMethod.QR_CODE_SHOW)
|
||||
.apply {
|
||||
if (hardwareInfo.hasBackCamera()) {
|
||||
// RiotX is able to scan QR codes, and a Camera is available
|
||||
add(VerificationMethod.QR_CODE_SCAN)
|
||||
} else {
|
||||
// This quite uncommon
|
||||
Timber.w("No back Camera detected")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,9 +63,11 @@ data class VerificationBottomSheetViewState(
|
|||
val isMe: Boolean = false
|
||||
) : MvRxState
|
||||
|
||||
class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: VerificationBottomSheetViewState,
|
||||
@Assisted args: VerificationBottomSheet.VerificationArgs,
|
||||
private val session: Session)
|
||||
class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: VerificationBottomSheetViewState,
|
||||
@Assisted args: VerificationBottomSheet.VerificationArgs,
|
||||
private val session: Session,
|
||||
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider)
|
||||
: VectorViewModel<VerificationBottomSheetViewState, VerificationAction, VerificationBottomSheetViewEvents>(initialState),
|
||||
VerificationService.Listener {
|
||||
|
||||
|
@ -116,9 +118,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
|||
if (autoReady) {
|
||||
// TODO, can I be here in DM mode? in this case should test if roomID is null?
|
||||
session.cryptoService().verificationService()
|
||||
.readyPendingVerification(supportedVerificationMethods,
|
||||
.readyPendingVerification(
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
pr!!.otherUserId,
|
||||
pr.transactionId ?: "")
|
||||
pr.transactionId ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +177,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
|||
session
|
||||
.cryptoService()
|
||||
.verificationService()
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethods, otherUserId, data, pendingLocalId)
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, data, pendingLocalId)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -191,7 +195,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
|||
pendingRequest = Success(session
|
||||
.cryptoService()
|
||||
.verificationService()
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethods, otherUserId, roomId)
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, roomId)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -362,9 +366,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
|||
// auto ready in this case, as we are waiting
|
||||
// TODO, can I be here in DM mode? in this case should test if roomID is null?
|
||||
session.cryptoService().verificationService()
|
||||
.readyPendingVerification(supportedVerificationMethods,
|
||||
.readyPendingVerification(
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
pr.otherUserId,
|
||||
pr.transactionId ?: "")
|
||||
pr.transactionId ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
// Use this one!
|
||||
|
|
|
@ -65,7 +65,7 @@ import im.vector.riotx.core.resources.UserPreferencesProvider
|
|||
import im.vector.riotx.core.utils.subscribeLogError
|
||||
import im.vector.riotx.features.command.CommandParser
|
||||
import im.vector.riotx.features.command.ParsedCommand
|
||||
import im.vector.riotx.features.crypto.verification.supportedVerificationMethods
|
||||
import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider
|
||||
import im.vector.riotx.features.home.room.detail.composer.rainbow.RainbowGenerator
|
||||
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||
import im.vector.riotx.features.home.room.typing.TypingHelper
|
||||
|
@ -81,13 +81,15 @@ import java.io.File
|
|||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
|
||||
userPreferencesProvider: UserPreferencesProvider,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val stringProvider: StringProvider,
|
||||
private val typingHelper: TypingHelper,
|
||||
private val rainbowGenerator: RainbowGenerator,
|
||||
private val session: Session
|
||||
class RoomDetailViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RoomDetailViewState,
|
||||
userPreferencesProvider: UserPreferencesProvider,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val stringProvider: StringProvider,
|
||||
private val typingHelper: TypingHelper,
|
||||
private val rainbowGenerator: RainbowGenerator,
|
||||
private val session: Session,
|
||||
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState), Timeline.Listener {
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
|
@ -421,7 +423,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||
session
|
||||
.cryptoService()
|
||||
.verificationService()
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethods, slashCommandResult.userId, room.roomId)
|
||||
.requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), slashCommandResult.userId, room.roomId)
|
||||
_viewEvents.post(RoomDetailViewEvents.SlashCommandHandled())
|
||||
popDraft()
|
||||
}
|
||||
|
@ -828,7 +830,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||
private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) {
|
||||
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}")
|
||||
if (session.cryptoService().verificationService().readyPendingVerificationInDMs(
|
||||
supportedVerificationMethods,
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
action.otherUserId,
|
||||
room.roomId,
|
||||
action.transactionId)) {
|
||||
|
|
|
@ -24,7 +24,6 @@ import androidx.core.app.ActivityOptionsCompat
|
|||
import androidx.core.app.TaskStackBuilder
|
||||
import androidx.core.view.ViewCompat
|
||||
import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerificationTransaction
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
||||
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
|
||||
import im.vector.matrix.android.api.util.MatrixItem
|
||||
import im.vector.riotx.R
|
||||
|
@ -35,6 +34,7 @@ import im.vector.riotx.core.utils.toast
|
|||
import im.vector.riotx.features.createdirect.CreateDirectRoomActivity
|
||||
import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
||||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity
|
||||
import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider
|
||||
import im.vector.riotx.features.crypto.verification.VerificationBottomSheet
|
||||
import im.vector.riotx.features.debug.DebugMenuActivity
|
||||
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
||||
|
@ -56,7 +56,8 @@ import javax.inject.Singleton
|
|||
@Singleton
|
||||
class DefaultNavigator @Inject constructor(
|
||||
private val sessionHolder: ActiveSessionHolder,
|
||||
private val vectorPreferences: VectorPreferences
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider
|
||||
) : Navigator {
|
||||
|
||||
override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) {
|
||||
|
@ -85,9 +86,10 @@ class DefaultNavigator @Inject constructor(
|
|||
override fun requestSessionVerification(context: Context) {
|
||||
val session = sessionHolder.getSafeActiveSession() ?: return
|
||||
val pr = session.cryptoService().verificationService().requestKeyVerification(
|
||||
listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW),
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
session.myUserId,
|
||||
session.cryptoService().getUserDevices(session.myUserId).map { it.deviceId })
|
||||
session.cryptoService().getUserDevices(session.myUserId).map { it.deviceId }
|
||||
)
|
||||
if (context is VectorBaseActivity) {
|
||||
VerificationBottomSheet.withArgs(
|
||||
roomId = null,
|
||||
|
|
|
@ -40,7 +40,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
|||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.features.crypto.verification.supportedVerificationMethods
|
||||
import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider
|
||||
|
||||
data class DevicesViewState(
|
||||
val myDeviceId: String = "",
|
||||
|
@ -50,8 +50,10 @@ data class DevicesViewState(
|
|||
val request: Async<Unit> = Uninitialized
|
||||
) : MvRxState
|
||||
|
||||
class DevicesViewModel @AssistedInject constructor(@Assisted initialState: DevicesViewState,
|
||||
private val session: Session)
|
||||
class DevicesViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: DevicesViewState,
|
||||
private val session: Session,
|
||||
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider)
|
||||
: VectorViewModel<DevicesViewState, DevicesAction, DevicesViewEvents>(initialState), VerificationService.Listener {
|
||||
|
||||
@AssistedInject.Factory
|
||||
|
@ -172,7 +174,9 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic
|
|||
}
|
||||
|
||||
private fun handleVerify(action: DevicesAction.VerifyMyDevice) {
|
||||
val txID = session.cryptoService().verificationService().requestKeyVerification(supportedVerificationMethods, session.myUserId, listOf(action.deviceId))
|
||||
val txID = session.cryptoService()
|
||||
.verificationService()
|
||||
.requestKeyVerification(supportedVerificationMethodsProvider.provide(), session.myUserId, listOf(action.deviceId))
|
||||
_viewEvents.post(DevicesViewEvents.ShowVerifyDevice(
|
||||
session.myUserId,
|
||||
txID.transactionId
|
||||
|
|
Loading…
Reference in a new issue