This repository has been archived by the owner on Jan 10, 2025. It is now read-only.
forked from mollyim/mollyim-android
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
app/src/unifiedpush/java/im/molly/unifiedpush/device/MollySocketDevice.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package im.molly.unifiedpush.device | ||
|
||
import org.signal.core.util.logging.Log | ||
import org.signal.libsignal.protocol.util.KeyHelper | ||
import org.thoughtcrime.securesms.AppCapabilities | ||
import org.thoughtcrime.securesms.crypto.PreKeyUtil | ||
import org.thoughtcrime.securesms.database.loaders.DeviceListLoader | ||
import org.thoughtcrime.securesms.dependencies.AppDependencies | ||
import org.thoughtcrime.securesms.devicelist.Device | ||
import org.thoughtcrime.securesms.keyvalue.SignalStore | ||
import org.thoughtcrime.securesms.push.AccountManagerFactory | ||
import org.thoughtcrime.securesms.registration.secondary.DeviceNameCipher | ||
import org.thoughtcrime.securesms.util.TextSecurePreferences | ||
import org.thoughtcrime.securesms.util.Util | ||
import org.whispersystems.signalservice.api.account.PreKeyUpload | ||
import org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse | ||
import org.whispersystems.signalservice.api.push.ServiceIdType | ||
import org.whispersystems.signalservice.api.push.SignalServiceAddress | ||
import im.molly.unifiedpush.store.MollySocketStore | ||
import java.io.IOException | ||
import java.nio.charset.Charset | ||
|
||
class MollySocketDevice { | ||
private val TAG = MollySocketDevice::class.java.simpleName | ||
private val DEVICE_NAME = "MollySocket" | ||
private val context = AppDependencies.application | ||
private val store = MollySocketStore() | ||
|
||
var socketUri: String? = null | ||
|
||
init { | ||
if(!isMollySocketDevicePresent()) { | ||
Log.d(TAG, "MollySocketDevice is not present") | ||
store.removeUri() | ||
} | ||
socketUri = store.getUri() | ||
?: run { | ||
newDevice() | ||
store.getUri() | ||
} | ||
} | ||
|
||
private fun isMollySocketDevicePresent(): Boolean { | ||
var devices : List<Device>? = emptyList() | ||
Thread { | ||
try { | ||
devices = DeviceListLoader(context, AppDependencies.signalServiceAccountManager).loadInBackground() | ||
} catch (e: IOException) { | ||
Log.e(TAG, "Encountered an IOException", e) | ||
} | ||
}.apply { | ||
start() | ||
join() | ||
} | ||
devices?.forEach { device -> | ||
if (device.id.toInt() == store.getDeviceId() && device.name == DEVICE_NAME) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
private fun newDevice() { | ||
Log.d(TAG, "Creating a device for MollySocket") | ||
|
||
Thread { | ||
try { | ||
val number = SignalStore.account.e164 ?: return@Thread | ||
val password = Util.getSecret(18) | ||
|
||
val verifyDeviceResponse = verifyNewDevice(number, password) | ||
TextSecurePreferences.setMultiDevice(context, true) | ||
|
||
generateAndRegisterPreKeys(number, verifyDeviceResponse.deviceId, password) | ||
store.saveDeviceId(verifyDeviceResponse.deviceId) | ||
store.saveUri(verifyDeviceResponse.uuid, verifyDeviceResponse.deviceId, password) | ||
} catch (e: IOException) { | ||
Log.e(TAG, "Encountered an IOException", e) | ||
} | ||
}.apply { | ||
start() | ||
join() | ||
} | ||
} | ||
|
||
@Throws(IOException::class) | ||
private fun verifyNewDevice(number: String, password: String): VerifyDeviceResponse { | ||
val verificationCode = AppDependencies.signalServiceAccountManager | ||
.newDeviceVerificationCode | ||
val registrationId = KeyHelper.generateRegistrationId(false) | ||
val encryptedDeviceName = DeviceNameCipher.encryptDeviceName( | ||
DEVICE_NAME.toByteArray(Charset.forName("UTF-8")), | ||
SignalStore.account.aciIdentityKey | ||
) | ||
|
||
return AccountManagerFactory.getInstance().createUnauthenticated(context, number, SignalServiceAddress.DEFAULT_DEVICE_ID, password) | ||
.verifySecondaryDevice( | ||
verificationCode, | ||
registrationId, | ||
true, | ||
"".toByteArray(), | ||
true, | ||
AppCapabilities.getCapabilities(true), | ||
false, | ||
encryptedDeviceName, | ||
SignalStore.account.pniRegistrationId | ||
) | ||
} | ||
|
||
@Throws(IOException::class) | ||
private fun generateAndRegisterPreKeys(number: String, deviceId: Int, password: String): Boolean? { | ||
val protocolStore = AppDependencies.protocolStore.aci() | ||
val accountManager = AccountManagerFactory.getInstance().createAuthenticated( | ||
context, | ||
SignalStore.account.aci ?: return null, | ||
SignalStore.account.pni ?: return null, | ||
number, | ||
deviceId, | ||
password | ||
) | ||
val metadataStore = SignalStore.account.aciPreKeys | ||
val signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore) | ||
val oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimeEcPreKeys(protocolStore, metadataStore) | ||
accountManager.setPreKeys( | ||
PreKeyUpload( | ||
serviceIdType = ServiceIdType.ACI, | ||
signedPreKey = signedPreKey, | ||
oneTimeEcPreKeys = oneTimePreKeys, | ||
lastResortKyberPreKey = null, | ||
oneTimeKyberPreKeys = null | ||
) | ||
) | ||
metadataStore.activeSignedPreKeyId = signedPreKey.id | ||
metadataStore.isSignedPreKeyRegistered = true | ||
return true | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
app/src/unifiedpush/java/im/molly/unifiedpush/helper/UnifiedPushHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package im.molly.unifiedpush.helper | ||
|
||
import org.signal.core.util.logging.Log | ||
import org.unifiedpush.android.connector.UnifiedPush.registerAppWithDialog | ||
import im.molly.unifiedpush.device.MollySocketDevice | ||
import org.thoughtcrime.securesms.dependencies.AppDependencies | ||
|
||
object UnifiedPushHelper{ | ||
private val TAG = Log.tag(UnifiedPushHelper::class.java) | ||
|
||
@JvmStatic | ||
fun initializeUnifiedPush() { | ||
Log.d(TAG, "##unifiedpush") | ||
val socketUri = MollySocketDevice().socketUri | ||
Log.d(TAG, socketUri) | ||
registerAppWithDialog(AppDependencies.application) | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
app/src/unifiedpush/java/im/molly/unifiedpush/receiver/UnifiedPushReceiver.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package im.molly.unifiedpush.receiver | ||
|
||
import android.content.Context | ||
import android.os.Build | ||
import org.signal.core.util.logging.Log | ||
import org.thoughtcrime.securesms.gcm.FcmFetchManager.enqueue | ||
import org.unifiedpush.android.connector.MessagingReceiver | ||
|
||
class UnifiedPushReceiver: MessagingReceiver() { | ||
private val TAG = Log.tag(UnifiedPushReceiver::class.java) | ||
|
||
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) { | ||
Log.d(TAG, "New endpoint: $endpoint") | ||
} | ||
|
||
override fun onRegistrationFailed(context: Context, instance: String) { | ||
// called when the registration is not possible, eg. no network | ||
} | ||
|
||
override fun onUnregistered(context: Context, instance: String) { | ||
// called when this application is unregistered from receiving push messages | ||
// TODO : start inapp webSocket | ||
} | ||
|
||
override fun onMessage(context: Context, message: ByteArray, instance: String) { | ||
Log.d(TAG, "New message") | ||
if (Build.VERSION.SDK_INT >= 31) { | ||
enqueue(context, true) | ||
} else { | ||
enqueue(context, false) | ||
} | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
app/src/unifiedpush/java/im/molly/unifiedpush/store/MollySocketStore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package im.molly.unifiedpush.store | ||
|
||
import android.content.Context | ||
import org.thoughtcrime.securesms.dependencies.AppDependencies | ||
import org.whispersystems.signalservice.api.push.SignalServiceAddress | ||
import java.util.UUID | ||
|
||
class MollySocketStore { | ||
private val PREF_MASTER = "unifiedpush" | ||
private val PREF_MASTER_SOCKET_URI = "unifiedpush.socketUri" | ||
private val PREF_MASTER_DEVICE_ID = "unifiedpush.deviceId" | ||
|
||
private val context = AppDependencies.application | ||
private val prefs = context.getSharedPreferences(PREF_MASTER, Context.MODE_PRIVATE) | ||
|
||
fun getUri(): String? { | ||
return prefs.getString(PREF_MASTER_SOCKET_URI, null) | ||
} | ||
|
||
private fun saveUri(uri: String) { | ||
prefs.edit()?.putString(PREF_MASTER_SOCKET_URI, uri)?.apply() | ||
} | ||
|
||
fun saveUri(uuid: UUID, deviceId: Int, password: String) { | ||
val wsUriFormat = AppDependencies.signalServiceNetworkAccess.getConfiguration() | ||
.signalServiceUrls[0].url | ||
.replace("https://", "wss://") | ||
.replace("http://", "ws://") + "/v1/websocket/?login=%s.%s&password=%s" | ||
|
||
saveUri( | ||
String.format(wsUriFormat, uuid, deviceId, password) | ||
) | ||
} | ||
|
||
fun removeUri() { | ||
prefs.edit().remove(PREF_MASTER_SOCKET_URI).apply() | ||
} | ||
|
||
fun getDeviceId(): Int { | ||
return prefs.getInt(PREF_MASTER_DEVICE_ID, SignalServiceAddress.DEFAULT_DEVICE_ID) | ||
} | ||
|
||
fun saveDeviceId(deviceId: Int) { | ||
prefs.edit().putInt(PREF_MASTER_DEVICE_ID, deviceId).apply() | ||
} | ||
|
||
fun removeDeviceId() { | ||
prefs.edit().remove(PREF_MASTER_DEVICE_ID).apply() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters