From ac9c9f534ef10de109a1cdfdcd63947287edf2a7 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Tue, 8 Oct 2019 14:28:30 +1100 Subject: [PATCH] Somewhat simplify device linking UI --- .../securesms/loki/DeviceLinkingDialog.kt | 42 ++++--------------- .../loki/DeviceLinkingDialogDelegate.kt | 3 +- .../securesms/loki/DeviceLinkingView.kt | 28 ++++++------- .../loki/DeviceLinkingViewDelegate.kt | 4 +- .../securesms/loki/MultiDeviceUtilities.kt | 1 - .../securesms/loki/SeedActivity.kt | 23 ++++++++-- 6 files changed, 45 insertions(+), 56 deletions(-) diff --git a/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialog.kt b/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialog.kt index 5f43280a0e..d5faaaca16 100644 --- a/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialog.kt +++ b/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialog.kt @@ -2,22 +2,16 @@ package org.thoughtcrime.securesms.loki import android.content.Context import android.support.v7.app.AlertDialog -import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.DatabaseFactory -import org.thoughtcrime.securesms.logging.Log import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.loki.api.DeviceLinkingSession import org.whispersystems.signalservice.loki.api.DeviceLinkingSessionListener -import org.whispersystems.signalservice.loki.api.LokiStorageAPI import org.whispersystems.signalservice.loki.api.PairingAuthorisation -import org.whispersystems.signalservice.loki.utilities.retryIfNeeded class DeviceLinkingDialog private constructor(private val context: Context, private val mode: DeviceLinkingView.Mode, private val delegate: DeviceLinkingDialogDelegate?) : DeviceLinkingViewDelegate, DeviceLinkingSessionListener { private lateinit var view: DeviceLinkingView private lateinit var dialog: AlertDialog - private val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize() - companion object { fun show(context: Context, mode: DeviceLinkingView.Mode, delegate: DeviceLinkingDialogDelegate?): DeviceLinkingDialog { @@ -31,42 +25,18 @@ class DeviceLinkingDialog private constructor(private val context: Context, priv view = DeviceLinkingView(context, mode, this) dialog = AlertDialog.Builder(context).setView(view).show() view.dismiss = { dismiss() } - startListening() - } - - public fun dismiss() { - stopListening() - dialog.dismiss() - } - - private fun startListening() { DeviceLinkingSession.shared.startListeningForLinkingRequests() DeviceLinkingSession.shared.addListener(this) } - private fun stopListening() { + private fun dismiss() { DeviceLinkingSession.shared.stopListeningForLinkingRequests() DeviceLinkingSession.shared.removeListener(this) + dialog.dismiss() } - override fun sendPairingAuthorizedMessage(pairing: PairingAuthorisation): Boolean { - val signedAuthorisation = pairing.sign(PairingAuthorisation.Type.GRANT, userPrivateKey) - if (signedAuthorisation == null || signedAuthorisation.type != PairingAuthorisation.Type.GRANT) { - Log.d("Loki", "Failed to sign pairing authorization.") - return false - } - retryIfNeeded(8) { - sendPairingAuthorisationMessage(context, pairing.secondaryDevicePublicKey, signedAuthorisation).get() - }.fail { - Log.d("Loki", "Failed to send pairing authorization message to ${pairing.secondaryDevicePublicKey}.") - } - DatabaseFactory.getLokiAPIDatabase(context).insertOrUpdatePairingAuthorisation(signedAuthorisation) - LokiStorageAPI.shared.updateUserDeviceMappings() - return true - } - - override fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { - delegate?.handleDeviceLinkAuthorized(pairing) + override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { + delegate?.handleDeviceLinkAuthorized(pairingAuthorisation) } override fun handleDeviceLinkingDialogDismissed() { @@ -77,6 +47,10 @@ class DeviceLinkingDialog private constructor(private val context: Context, priv delegate?.handleDeviceLinkingDialogDismissed() } + override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { + delegate?.sendPairingAuthorizedMessage(pairingAuthorisation) + } + override fun requestUserAuthorization(authorisation: PairingAuthorisation) { Util.runOnMain { view.requestUserAuthorization(authorisation) diff --git a/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialogDelegate.kt b/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialogDelegate.kt index 7f0d5ebf80..48493e25e2 100644 --- a/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialogDelegate.kt +++ b/src/org/thoughtcrime/securesms/loki/DeviceLinkingDialogDelegate.kt @@ -4,6 +4,7 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation interface DeviceLinkingDialogDelegate { - fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { } + fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { } fun handleDeviceLinkingDialogDismissed() { } + fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/DeviceLinkingView.kt b/src/org/thoughtcrime/securesms/loki/DeviceLinkingView.kt index 924deb16e0..b7983cc92b 100644 --- a/src/org/thoughtcrime/securesms/loki/DeviceLinkingView.kt +++ b/src/org/thoughtcrime/securesms/loki/DeviceLinkingView.kt @@ -82,11 +82,9 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe // endregion // region Device Linking - fun requestUserAuthorization(authorisation: PairingAuthorisation) { - if (mode != Mode.Master) { throw IllegalStateException() } - if (authorisation.type != PairingAuthorisation.Type.REQUEST) { throw IllegalStateException() } - if (pairingAuthorisation != null) { return } - pairingAuthorisation = authorisation + fun requestUserAuthorization(pairingAuthorisation: PairingAuthorisation) { + if (mode != Mode.Master || pairingAuthorisation.type != PairingAuthorisation.Type.REQUEST || this.pairingAuthorisation != null) { return } + this.pairingAuthorisation = pairingAuthorisation spinner.visibility = View.GONE val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams titleTextViewLayoutParams.topMargin = toPx(16, resources) @@ -94,14 +92,14 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe titleTextView.text = resources.getString(R.string.view_device_linking_title_3) explanationTextView.text = resources.getString(R.string.view_device_linking_explanation_2) mnemonicTextView.visibility = View.VISIBLE - val hexEncodedPublicKey = authorisation.secondaryDevicePublicKey.removing05PrefixIfNeeded() + val hexEncodedPublicKey = pairingAuthorisation.secondaryDevicePublicKey.removing05PrefixIfNeeded() mnemonicTextView.text = MnemonicCodec(languageFileDirectory).encode(hexEncodedPublicKey).split(" ").slice(0 until 3).joinToString(" ") authorizeButton.visibility = View.VISIBLE } - fun onDeviceLinkAuthorized(authorisation: PairingAuthorisation) { - if (mode != Mode.Slave || pairingAuthorisation != null) { return } - pairingAuthorisation = authorisation + fun onDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { + if (mode != Mode.Slave || pairingAuthorisation.type != PairingAuthorisation.Type.GRANT || this.pairingAuthorisation != null) { return } + this.pairingAuthorisation = pairingAuthorisation spinner.visibility = View.GONE val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams titleTextViewLayoutParams.topMargin = toPx(8, resources) @@ -116,7 +114,7 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe buttonContainer.visibility = View.GONE cancelButton.visibility = View.GONE Handler().postDelayed({ - delegate.handleDeviceLinkAuthorized(authorisation) + delegate.handleDeviceLinkAuthorized(pairingAuthorisation) dismiss?.invoke() }, 4000) } @@ -124,11 +122,11 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe // region Interaction private fun authorizePairing() { - if (pairingAuthorisation == null || mode != Mode.Master ) { return; } - if (delegate.sendPairingAuthorizedMessage(pairingAuthorisation!!)) { - delegate.handleDeviceLinkAuthorized(pairingAuthorisation!!) - dismiss?.invoke() - } + val pairingAuthorisation = this.pairingAuthorisation + if (mode != Mode.Master || pairingAuthorisation == null) { return; } + delegate.sendPairingAuthorizedMessage(pairingAuthorisation) + delegate.handleDeviceLinkAuthorized(pairingAuthorisation) + dismiss?.invoke() } private fun cancel() { diff --git a/src/org/thoughtcrime/securesms/loki/DeviceLinkingViewDelegate.kt b/src/org/thoughtcrime/securesms/loki/DeviceLinkingViewDelegate.kt index a82987964e..56c77bd9c7 100644 --- a/src/org/thoughtcrime/securesms/loki/DeviceLinkingViewDelegate.kt +++ b/src/org/thoughtcrime/securesms/loki/DeviceLinkingViewDelegate.kt @@ -4,7 +4,7 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation interface DeviceLinkingViewDelegate { - fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { } + fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { } fun handleDeviceLinkingDialogDismissed() { } - fun sendPairingAuthorizedMessage(pairing: PairingAuthorisation): Boolean { return false } + fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt index 22f272e59a..adaee4ef49 100644 --- a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt +++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt @@ -57,7 +57,6 @@ fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Conte } deferred.resolve(lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS) } - return deferred.promise } diff --git a/src/org/thoughtcrime/securesms/loki/SeedActivity.kt b/src/org/thoughtcrime/securesms/loki/SeedActivity.kt index 8c4341d6f1..8da00fe60c 100644 --- a/src/org/thoughtcrime/securesms/loki/SeedActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/SeedActivity.kt @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.util.Hex import org.thoughtcrime.securesms.util.TextSecurePreferences import org.whispersystems.curve25519.Curve25519 import org.whispersystems.libsignal.util.KeyHelper +import org.whispersystems.signalservice.loki.api.LokiStorageAPI import org.whispersystems.signalservice.loki.api.PairingAuthorisation import org.whispersystems.signalservice.loki.crypto.MnemonicCodec import org.whispersystems.signalservice.loki.utilities.Analytics @@ -217,10 +218,10 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate { } } - override fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { + override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { Analytics.shared.track("Device Linked Successfully") - if (pairing.secondaryDevicePublicKey == TextSecurePreferences.getLocalNumber(this)) { - TextSecurePreferences.setMasterHexEncodedPublicKey(this, pairing.primaryDevicePublicKey) + if (pairingAuthorisation.secondaryDevicePublicKey == TextSecurePreferences.getLocalNumber(this)) { + TextSecurePreferences.setMasterHexEncodedPublicKey(this, pairingAuthorisation.primaryDevicePublicKey) } startActivity(Intent(this, ConversationListActivity::class.java)) finish() @@ -230,6 +231,22 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate { resetForRegistration() } + override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { + val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).privateKey.serialize() + val signedPairingAuthorisation = pairingAuthorisation.sign(PairingAuthorisation.Type.GRANT, userPrivateKey) + if (signedPairingAuthorisation == null || signedPairingAuthorisation.type != PairingAuthorisation.Type.GRANT) { + Log.d("Loki", "Failed to sign pairing authorization.") + return + } + retryIfNeeded(8) { + sendPairingAuthorisationMessage(this, pairingAuthorisation.secondaryDevicePublicKey, signedPairingAuthorisation).get() + }.fail { + Log.d("Loki", "Failed to send pairing authorization message to ${pairingAuthorisation.secondaryDevicePublicKey}.") + } + DatabaseFactory.getLokiAPIDatabase(this).insertOrUpdatePairingAuthorisation(signedPairingAuthorisation) + LokiStorageAPI.shared.updateUserDeviceMappings() + } + private fun resetForRegistration() { IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey) TextSecurePreferences.removeLocalRegistrationId(this)