mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 16:57:50 +00:00
Refactor multi device
This commit is contained in:
parent
9c71a4c3cd
commit
07b1ffa77e
@ -184,9 +184,12 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
setUpP2PAPI();
|
setUpP2PAPI();
|
||||||
// Loki - Update device mappings
|
// Loki - Update device mappings
|
||||||
if (setUpStorageAPIIfNeeded()) {
|
if (setUpStorageAPIIfNeeded()) {
|
||||||
LokiFileServerAPI.Companion.getShared().updateUserDeviceLinks();
|
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
if (TextSecurePreferences.needsRevocationCheck(this)) {
|
if (userHexEncodedPublicKey != null) {
|
||||||
checkNeedsRevocation();
|
LokiFileServerAPI.Companion.getShared().getDeviceLinks(userHexEncodedPublicKey, true);
|
||||||
|
if (TextSecurePreferences.getNeedsIsRevokedSlaveDeviceCheck(this)) {
|
||||||
|
MultiDeviceUtilities.checkIsRevokedSlaveDevice(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loki - Set up public chat manager
|
// Loki - Set up public chat manager
|
||||||
@ -613,11 +616,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// endregion
|
|
||||||
|
|
||||||
public void checkNeedsRevocation() {
|
|
||||||
MultiDeviceUtilities.checkForRevocation(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkNeedsDatabaseReset() {
|
public void checkNeedsDatabaseReset() {
|
||||||
if (TextSecurePreferences.resetDatabase(this)) {
|
if (TextSecurePreferences.resetDatabase(this)) {
|
||||||
@ -643,4 +641,5 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
this.startActivity(mainIntent);
|
this.startActivity(mainIntent);
|
||||||
Runtime.getRuntime().exit(0);
|
Runtime.getRuntime().exit(0);
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,6 @@ import org.whispersystems.signalservice.loki.api.DeviceLink;
|
|||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession;
|
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiDeviceLinkUtilities;
|
import org.whispersystems.signalservice.loki.api.LokiDeviceLinkUtilities;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI;
|
|
||||||
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
|
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
|
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiServiceMessage;
|
import org.whispersystems.signalservice.loki.messaging.LokiServiceMessage;
|
||||||
@ -336,7 +335,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
String ourMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
String ourMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
if (ourMasterDevice != null && ourMasterDevice.equals(content.getSender())) {
|
if (ourMasterDevice != null && ourMasterDevice.equals(content.getSender())) {
|
||||||
TextSecurePreferences.setDatabaseResetFromUnpair(context, true);
|
TextSecurePreferences.setDatabaseResetFromUnpair(context, true);
|
||||||
MultiDeviceUtilities.checkForRevocation(context);
|
MultiDeviceUtilities.checkIsRevokedSlaveDevice(context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Loki - Don't process session restore message any further
|
// Loki - Don't process session restore message any further
|
||||||
@ -1170,8 +1169,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
TextSecurePreferences.setMultiDevice(context, true);
|
TextSecurePreferences.setMultiDevice(context, true);
|
||||||
// Send a background message to the master device
|
// Send a background message to the master device
|
||||||
MessageSender.sendBackgroundMessage(context, deviceLink.getMasterHexEncodedPublicKey());
|
MessageSender.sendBackgroundMessage(context, deviceLink.getMasterHexEncodedPublicKey());
|
||||||
// Propagate the updates to the file server
|
|
||||||
LokiFileServerAPI.Companion.getShared().updateUserDeviceLinks();
|
|
||||||
// Update display name if needed
|
// Update display name if needed
|
||||||
if (content.senderDisplayName.isPresent() && content.senderDisplayName.get().length() > 0) {
|
if (content.senderDisplayName.isPresent() && content.senderDisplayName.get().length() > 0) {
|
||||||
TextSecurePreferences.setProfileName(context, content.senderDisplayName.get());
|
TextSecurePreferences.setProfileName(context, content.senderDisplayName.get());
|
||||||
@ -1184,6 +1181,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
if (content.getSyncMessage().isPresent() && content.getSyncMessage().get().getContacts().isPresent()) {
|
if (content.getSyncMessage().isPresent() && content.getSyncMessage().get().getContacts().isPresent()) {
|
||||||
handleContactSyncMessage(content.getSyncMessage().get().getContacts().get());
|
handleContactSyncMessage(content.getSyncMessage().get().getContacts().get());
|
||||||
}
|
}
|
||||||
|
// The device link is propagated to the file server in LandingActivity.onDeviceLinkAuthorized because we can handle the error there
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDisplayName(String hexEncodedPublicKey, String profileName) {
|
private void setDisplayName(String hexEncodedPublicKey, String profileName) {
|
||||||
@ -1775,7 +1773,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
*/
|
*/
|
||||||
private Recipient getMasterRecipient(String hexEncodedPublicKey) {
|
private Recipient getMasterRecipient(String hexEncodedPublicKey) {
|
||||||
try {
|
try {
|
||||||
String masterHexEncodedPublicKey = PromiseUtil.timeout(LokiDeviceLinkUtilities.INSTANCE.getMasterHexEncodedPublicKey(hexEncodedPublicKey), 5000).get();
|
String masterHexEncodedPublicKey = LokiDeviceLinkUtilities.INSTANCE.getMasterHexEncodedPublicKey(hexEncodedPublicKey).get();
|
||||||
String targetHexEncodedPublicKey = (masterHexEncodedPublicKey != null) ? masterHexEncodedPublicKey : hexEncodedPublicKey;
|
String targetHexEncodedPublicKey = (masterHexEncodedPublicKey != null) ? masterHexEncodedPublicKey : hexEncodedPublicKey;
|
||||||
// If the public key matches our master device then we need to forward the message to ourselves (note to self)
|
// If the public key matches our master device then we need to forward the message to ourselves (note to self)
|
||||||
String ourMasterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
String ourMasterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
|
@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.loki
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.all
|
|
||||||
import nl.komponents.kovenant.functional.bind
|
import nl.komponents.kovenant.functional.bind
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
import nl.komponents.kovenant.toFailVoid
|
import nl.komponents.kovenant.toFailVoid
|
||||||
@ -16,7 +15,6 @@ import org.thoughtcrime.securesms.database.Address
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.logging.Log
|
import org.thoughtcrime.securesms.logging.Log
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
@ -26,25 +24,21 @@ import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
|||||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
||||||
import org.whispersystems.signalservice.loki.utilities.recover
|
import org.whispersystems.signalservice.loki.utilities.recover
|
||||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||||
import java.util.*
|
|
||||||
import kotlin.concurrent.schedule
|
|
||||||
|
|
||||||
fun checkForRevocation(context: Context) {
|
fun checkIsRevokedSlaveDevice(context: Context) {
|
||||||
val primaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context) ?: return
|
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) ?: return
|
||||||
val ourDevice = TextSecurePreferences.getLocalNumber(context)
|
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
|
LokiFileServerAPI.shared.getDeviceLinks(masterHexEncodedPublicKey, true).bind { deviceLinks ->
|
||||||
LokiFileServerAPI.shared.getDeviceLinks(primaryDevice, true).bind { mappings ->
|
val deviceLink = deviceLinks.find { it.masterHexEncodedPublicKey == masterHexEncodedPublicKey && it.slaveHexEncodedPublicKey == hexEncodedPublicKey }
|
||||||
val ourMapping = mappings.find { it.slaveHexEncodedPublicKey == ourDevice }
|
if (deviceLink != null) throw Error("Device hasn't been revoked.")
|
||||||
if (ourMapping != null) throw Error("Device has not been revoked")
|
DatabaseFactory.getLokiAPIDatabase(context).clearDeviceLinks(hexEncodedPublicKey)
|
||||||
// remove pairing authorisations for our device
|
LokiFileServerAPI.shared.setDeviceLinks(setOf())
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).clearDeviceLinks(ourDevice)
|
|
||||||
LokiFileServerAPI.shared.updateUserDeviceLinks()
|
|
||||||
}.successUi {
|
}.successUi {
|
||||||
TextSecurePreferences.setNeedsRevocationCheck(context, false)
|
TextSecurePreferences.setNeedsIsRevokedSlaveDeviceCheck(context, false)
|
||||||
ApplicationContext.getInstance(context).clearData()
|
ApplicationContext.getInstance(context).clearData()
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
TextSecurePreferences.setNeedsRevocationCheck(context, true)
|
TextSecurePreferences.setNeedsIsRevokedSlaveDeviceCheck(context, true)
|
||||||
Log.d("Loki", "Revocation check failed: ${error.message ?: error}")
|
Log.d("Loki", "Revocation check failed due to error: ${error.message ?: error}.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,66 +103,44 @@ fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: DeviceLink): Promise<Unit, Exception> {
|
fun sendDeviceLinkMessage(context: Context, hexEncodedPublicKey: String, deviceLink: DeviceLink): Promise<Unit, Exception> {
|
||||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||||
val address = SignalServiceAddress(contactHexEncodedPublicKey)
|
val address = SignalServiceAddress(hexEncodedPublicKey)
|
||||||
val message = SignalServiceDataMessage.newBuilder().withDeviceLink(authorisation)
|
val message = SignalServiceDataMessage.newBuilder().withDeviceLink(deviceLink)
|
||||||
// A REQUEST should always act as a friend request. A GRANT should always be replying back as a normal message.
|
// A REQUEST should always act as a friend request. An AUTHORIZATION should always be a normal message.
|
||||||
if (authorisation.type == DeviceLink.Type.REQUEST) {
|
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
||||||
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
||||||
message.asFriendRequest(true).withPreKeyBundle(preKeyBundle)
|
message.asFriendRequest(true).withPreKeyBundle(preKeyBundle)
|
||||||
} else {
|
} else {
|
||||||
// Send over our profile key so that our linked device can get our profile picture
|
// Send over our profile key so that our linked device can get our profile picture
|
||||||
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
Log.d("Loki", "Sending authorisation message to: $contactHexEncodedPublicKey.")
|
Log.d("Loki", "Sending device link message to: $hexEncodedPublicKey.")
|
||||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(contactHexEncodedPublicKey), false))
|
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false))
|
||||||
val result = messageSender.sendMessage(0, address, udAccess, message.build())
|
val result = messageSender.sendMessage(0, address, udAccess, message.build())
|
||||||
if (result.success == null) {
|
if (result.success == null) {
|
||||||
val exception = when {
|
val exception = when {
|
||||||
result.isNetworkFailure -> "Failed to send authorisation message due to a network error."
|
result.isNetworkFailure -> "Failed to send device link message due to a network error."
|
||||||
else -> "Failed to send authorisation message."
|
else -> "Failed to send device link message."
|
||||||
}
|
}
|
||||||
throw Exception(exception)
|
throw Exception(exception)
|
||||||
}
|
}
|
||||||
Promise.ofSuccess(Unit)
|
Promise.ofSuccess(Unit)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send authorisation message to: $contactHexEncodedPublicKey.")
|
Log.d("Loki", "Failed to send device link message to: $hexEncodedPublicKey.")
|
||||||
Promise.ofFail(e)
|
Promise.ofFail(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun signAndSendPairingAuthorisationMessage(context: Context, pairingAuthorisation: DeviceLink) {
|
fun signAndSendDeviceLinkMessage(context: Context, deviceLink: DeviceLink): Promise<Unit, Exception> {
|
||||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||||
val signedPairingAuthorisation = pairingAuthorisation.sign(DeviceLink.Type.AUTHORIZATION, userPrivateKey)
|
val signedDeviceLink = deviceLink.sign(DeviceLink.Type.AUTHORIZATION, userPrivateKey)
|
||||||
if (signedPairingAuthorisation == null || signedPairingAuthorisation.type != DeviceLink.Type.AUTHORIZATION) {
|
if (signedDeviceLink == null || signedDeviceLink.type != DeviceLink.Type.AUTHORIZATION) {
|
||||||
Log.d("Loki", "Failed to sign pairing authorization.")
|
return Promise.ofFail(Exception("Failed to sign device link."))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).addDeviceLink(signedPairingAuthorisation)
|
return retryIfNeeded(8) {
|
||||||
TextSecurePreferences.setMultiDevice(context, true)
|
sendDeviceLinkMessage(context, deviceLink.slaveHexEncodedPublicKey, signedDeviceLink)
|
||||||
|
|
||||||
val address = Address.fromSerialized(pairingAuthorisation.slaveHexEncodedPublicKey)
|
|
||||||
|
|
||||||
val sendPromise = retryIfNeeded(8) {
|
|
||||||
sendPairingAuthorisationMessage(context, address.serialize(), signedPairingAuthorisation)
|
|
||||||
}.fail {
|
|
||||||
Log.d("Loki", "Failed to send pairing authorization message to ${address.serialize()}.")
|
|
||||||
}
|
|
||||||
|
|
||||||
val updatePromise = LokiFileServerAPI.shared.updateUserDeviceLinks().fail {
|
|
||||||
Log.d("Loki", "Failed to update device mapping")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If both promises complete successfully then we should sync our contacts
|
|
||||||
all(listOf(sendPromise, updatePromise), cancelOthersOnError = false).success {
|
|
||||||
Log.d("Loki", "Successfully pairing with a secondary device! Syncing contacts.")
|
|
||||||
// Send out sync contact after a delay
|
|
||||||
Timer().schedule(3000) {
|
|
||||||
MessageSender.syncAllContacts(context, address)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceSlaveModeDialo
|
|||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.push
|
import org.thoughtcrime.securesms.loki.redesign.utilities.push
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.setUpActionBarSessionLogo
|
import org.thoughtcrime.securesms.loki.redesign.utilities.setUpActionBarSessionLogo
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
||||||
import org.thoughtcrime.securesms.loki.sendPairingAuthorisationMessage
|
import org.thoughtcrime.securesms.loki.sendDeviceLinkMessage
|
||||||
import org.thoughtcrime.securesms.util.Base64
|
import org.thoughtcrime.securesms.util.Base64
|
||||||
import org.thoughtcrime.securesms.util.Hex
|
import org.thoughtcrime.securesms.util.Hex
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
@ -27,6 +27,7 @@ import org.whispersystems.libsignal.ecc.Curve
|
|||||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||||
import org.whispersystems.libsignal.util.KeyHelper
|
import org.whispersystems.libsignal.util.KeyHelper
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLink
|
import org.whispersystems.signalservice.loki.api.DeviceLink
|
||||||
|
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
||||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||||
|
|
||||||
@ -92,11 +93,11 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
|||||||
TextSecurePreferences.setLocalNumber(this, userHexEncodedPublicKey)
|
TextSecurePreferences.setLocalNumber(this, userHexEncodedPublicKey)
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
||||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
||||||
val authorisation = DeviceLink(hexEncodedPublicKey, userHexEncodedPublicKey).sign(DeviceLink.Type.REQUEST, keyPair!!.privateKey.serialize())
|
val deviceLink = DeviceLink(hexEncodedPublicKey, userHexEncodedPublicKey).sign(DeviceLink.Type.REQUEST, keyPair!!.privateKey.serialize())
|
||||||
if (authorisation == null) {
|
if (deviceLink == null) {
|
||||||
Log.d("Loki", "Failed to sign device link request.")
|
Log.d("Loki", "Failed to sign device link request.")
|
||||||
reset()
|
reset()
|
||||||
return Toast.makeText(application, "Couldn't link device.", Toast.LENGTH_SHORT).show()
|
return Toast.makeText(application, "Couldn't link device.", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
val application = ApplicationContext.getInstance(this)
|
val application = ApplicationContext.getInstance(this)
|
||||||
application.startLongPollingIfNeeded()
|
application.startLongPollingIfNeeded()
|
||||||
@ -107,12 +108,13 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
|||||||
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
||||||
AsyncTask.execute {
|
AsyncTask.execute {
|
||||||
retryIfNeeded(8) {
|
retryIfNeeded(8) {
|
||||||
sendPairingAuthorisationMessage(this@LandingActivity, authorisation.masterHexEncodedPublicKey, authorisation)
|
sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterHexEncodedPublicKey, deviceLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||||
|
LokiFileServerAPI.shared.addDeviceLink(deviceLink)
|
||||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
||||||
val intent = Intent(this, HomeActivity::class.java)
|
val intent = Intent(this, HomeActivity::class.java)
|
||||||
show(intent)
|
show(intent)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||||
|
|
||||||
import android.os.AsyncTask
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.LoaderManager
|
import android.support.v4.app.LoaderManager
|
||||||
import android.support.v4.content.Loader
|
import android.support.v4.content.Loader
|
||||||
@ -12,16 +11,20 @@ import android.view.View
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import kotlinx.android.synthetic.main.activity_linked_devices.*
|
import kotlinx.android.synthetic.main.activity_linked_devices.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import nl.komponents.kovenant.ui.failUi
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
|
import org.thoughtcrime.securesms.database.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.devicelist.Device
|
import org.thoughtcrime.securesms.devicelist.Device
|
||||||
import org.thoughtcrime.securesms.loki.redesign.dialogs.*
|
import org.thoughtcrime.securesms.loki.redesign.dialogs.*
|
||||||
import org.thoughtcrime.securesms.loki.signAndSendPairingAuthorisationMessage
|
import org.thoughtcrime.securesms.loki.signAndSendDeviceLinkMessage
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
import org.thoughtcrime.securesms.sms.MessageSender
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLink
|
import org.whispersystems.signalservice.loki.api.DeviceLink
|
||||||
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager.LoaderCallbacks<List<Device>>, DeviceClickListener, EditDeviceNameDialogDelegate, LinkDeviceMasterModeDialogDelegate {
|
class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager.LoaderCallbacks<List<Device>>, DeviceClickListener, EditDeviceNameDialogDelegate, LinkDeviceMasterModeDialogDelegate {
|
||||||
private var devices = listOf<Device>()
|
private var devices = listOf<Device>()
|
||||||
@ -118,20 +121,37 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
|||||||
private fun unlinkDevice(slaveDeviceHexEncodedPublicKey: String) {
|
private fun unlinkDevice(slaveDeviceHexEncodedPublicKey: String) {
|
||||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
||||||
database.removeDeviceLink(userHexEncodedPublicKey, slaveDeviceHexEncodedPublicKey)
|
val deviceLink = database.getDeviceLinks(userHexEncodedPublicKey).find { it.masterHexEncodedPublicKey == userHexEncodedPublicKey && it.slaveHexEncodedPublicKey == slaveDeviceHexEncodedPublicKey }
|
||||||
LokiFileServerAPI.shared.updateUserDeviceLinks().success {
|
if (deviceLink == null) {
|
||||||
MessageSender.sendUnpairRequest(this, slaveDeviceHexEncodedPublicKey)
|
return Toast.makeText(this, "Couldn't unlink device.", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
LokiFileServerAPI.shared.removeDeviceLink(deviceLink).success {
|
||||||
|
MessageSender.sendUnpairRequest(this, slaveDeviceHexEncodedPublicKey)
|
||||||
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
|
Toast.makeText(this, "Your device was unlinked successfully", Toast.LENGTH_LONG).show()
|
||||||
|
}.fail {
|
||||||
|
Toast.makeText(this, "Couldn't unlink device.", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
|
||||||
Toast.makeText(this, "Your device was unlinked successfully", Toast.LENGTH_LONG).show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeviceLinkRequestAuthorized(authorization: DeviceLink) {
|
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||||
AsyncTask.execute {
|
LokiFileServerAPI.shared.addDeviceLink(deviceLink).success {
|
||||||
signAndSendPairingAuthorisationMessage(this, authorization)
|
signAndSendDeviceLinkMessage(this, deviceLink).success {
|
||||||
Util.runOnMain {
|
TextSecurePreferences.setMultiDevice(this, true)
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
Util.runOnMain {
|
||||||
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
|
}
|
||||||
|
Timer().schedule(4000) {
|
||||||
|
MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey))
|
||||||
|
}
|
||||||
|
}.fail {
|
||||||
|
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||||
|
Util.runOnMain {
|
||||||
|
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}.failUi {
|
||||||
|
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +190,11 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}.toSet()
|
}.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun clearDeviceLinks(hexEncodedPublicKey: String) {
|
||||||
|
val database = databaseHelper.writableDatabase
|
||||||
|
database.delete(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( hexEncodedPublicKey, hexEncodedPublicKey ))
|
||||||
|
}
|
||||||
|
|
||||||
override fun addDeviceLink(deviceLink: DeviceLink) {
|
override fun addDeviceLink(deviceLink: DeviceLink) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val values = ContentValues()
|
val values = ContentValues()
|
||||||
@ -200,14 +205,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.insertOrUpdate(deviceLinkCache, values, "$masterHexEncodedPublicKey = ? AND $slaveHexEncodedPublicKey = ?", arrayOf( deviceLink.masterHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey ))
|
database.insertOrUpdate(deviceLinkCache, values, "$masterHexEncodedPublicKey = ? AND $slaveHexEncodedPublicKey = ?", arrayOf( deviceLink.masterHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearDeviceLinks(hexEncodedPublicKey: String) {
|
override fun removeDeviceLink(deviceLink: DeviceLink) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
database.delete(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( hexEncodedPublicKey, hexEncodedPublicKey ))
|
database.delete(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( deviceLink.masterHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey ))
|
||||||
}
|
|
||||||
|
|
||||||
fun removeDeviceLink(masterHexEncodedPublicKey: String, slaveHexEncodedPublicKey: String) {
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
database.delete(deviceLinkCache, "${Companion.masterHexEncodedPublicKey} = ? OR ${Companion.slaveHexEncodedPublicKey} = ?", arrayOf( masterHexEncodedPublicKey, slaveHexEncodedPublicKey ))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserCount(group: Long, server: String): Int? {
|
fun getUserCount(group: Long, server: String): Int? {
|
||||||
|
@ -1235,11 +1235,11 @@ public class TextSecurePreferences {
|
|||||||
return getBooleanPreference(context, "database_reset_unpair", false);
|
return getBooleanPreference(context, "database_reset_unpair", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNeedsRevocationCheck(Context context, boolean needsCheck) {
|
public static void setNeedsIsRevokedSlaveDeviceCheck(Context context, boolean value) {
|
||||||
setBooleanPreference(context, "needs_revocation", needsCheck);
|
setBooleanPreference(context, "needs_revocation", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean needsRevocationCheck(Context context) {
|
public static boolean getNeedsIsRevokedSlaveDeviceCheck(Context context) {
|
||||||
return getBooleanPreference(context, "needs_revocation", false);
|
return getBooleanPreference(context, "needs_revocation", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user