mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 20:45:17 +00:00
feat: finish latest wrappers fix tests and continue building default generation functions. refactor defaults to be used if no stored data blob in DB
This commit is contained in:
parent
c1434648dc
commit
2a701f2cc3
@ -8,8 +8,8 @@ import network.loki.messenger.libsession_util.UserProfile
|
|||||||
import org.session.libsession.utilities.ConfigFactoryProtocol
|
import org.session.libsession.utilities.ConfigFactoryProtocol
|
||||||
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
||||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||||
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import java.util.concurrent.ConcurrentSkipListSet
|
import java.util.concurrent.ConcurrentSkipListSet
|
||||||
|
|
||||||
class ConfigFactory(private val context: Context,
|
class ConfigFactory(private val context: Context,
|
||||||
@ -42,14 +42,14 @@ class ConfigFactory(private val context: Context,
|
|||||||
|
|
||||||
override val user: UserProfile? get() = synchronized(userLock) {
|
override val user: UserProfile? get() = synchronized(userLock) {
|
||||||
if (_userConfig == null) {
|
if (_userConfig == null) {
|
||||||
Log.d("Loki-DBG", "Getting user info")
|
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||||
Log.d("Loki-DBG", "Getting user configs and hashes")
|
|
||||||
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
|
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
|
||||||
_userConfig = if (userDump != null) {
|
_userConfig = if (userDump != null) {
|
||||||
UserProfile.newInstance(secretKey, userDump)
|
UserProfile.newInstance(secretKey, userDump)
|
||||||
} else {
|
} else {
|
||||||
UserProfile.newInstance(secretKey)
|
ConfigurationMessageUtilities.generateUserProfileConfigDump()?.let { dump ->
|
||||||
|
UserProfile.newInstance(secretKey, dump)
|
||||||
|
} ?: UserProfile.newInstance(secretKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_userConfig
|
_userConfig
|
||||||
@ -62,7 +62,9 @@ class ConfigFactory(private val context: Context,
|
|||||||
_contacts = if (contactsDump != null) {
|
_contacts = if (contactsDump != null) {
|
||||||
Contacts.newInstance(secretKey, contactsDump)
|
Contacts.newInstance(secretKey, contactsDump)
|
||||||
} else {
|
} else {
|
||||||
Contacts.newInstance(secretKey)
|
ConfigurationMessageUtilities.generateContactConfigDump()?.let { dump ->
|
||||||
|
Contacts.newInstance(secretKey, dump)
|
||||||
|
} ?: Contacts.newInstance(secretKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_contacts
|
_contacts
|
||||||
@ -75,7 +77,10 @@ class ConfigFactory(private val context: Context,
|
|||||||
_convoVolatileConfig = if (convoDump != null) {
|
_convoVolatileConfig = if (convoDump != null) {
|
||||||
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
||||||
} else {
|
} else {
|
||||||
ConversationVolatileConfig.newInstance(secretKey)
|
// TODO: generate convo volatile config here
|
||||||
|
ConfigurationMessageUtilities.generateConversationVolatileDump(context)?.let { dump ->
|
||||||
|
ConversationVolatileConfig.newInstance(secretKey, dump)
|
||||||
|
} ?: ConversationVolatileConfig.newInstance(secretKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_convoVolatileConfig
|
_convoVolatileConfig
|
||||||
|
@ -15,6 +15,7 @@ import org.session.libsession.messaging.jobs.JobQueue
|
|||||||
import org.session.libsession.messaging.messages.Destination
|
import org.session.libsession.messaging.messages.Destination
|
||||||
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||||
|
import org.session.libsession.messaging.utilities.SessionId
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
@ -116,7 +117,7 @@ object ConfigurationMessageUtilities {
|
|||||||
return dump
|
return dump
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateContactConfigDump(context: Context): ByteArray? {
|
fun generateContactConfigDump(): ByteArray? {
|
||||||
val secretKey = maybeUserSecretKey() ?: return null
|
val secretKey = maybeUserSecretKey() ?: return null
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val localUserKey = storage.getUserPublicKey() ?: return null
|
val localUserKey = storage.getUserPublicKey() ?: return null
|
||||||
@ -142,7 +143,7 @@ object ConfigurationMessageUtilities {
|
|||||||
approved = settings.isApproved,
|
approved = settings.isApproved,
|
||||||
approvedMe = settings.hasApprovedMe(),
|
approvedMe = settings.hasApprovedMe(),
|
||||||
profilePicture = userPic ?: UserPic.DEFAULT,
|
profilePicture = userPic ?: UserPic.DEFAULT,
|
||||||
priority = 0 // TODO: read this in from a pinned priority
|
priority = if ()
|
||||||
)
|
)
|
||||||
contactConfig.set(contactInfo)
|
contactConfig.set(contactInfo)
|
||||||
}
|
}
|
||||||
@ -154,7 +155,6 @@ object ConfigurationMessageUtilities {
|
|||||||
fun generateConversationVolatileDump(context: Context): ByteArray? {
|
fun generateConversationVolatileDump(context: Context): ByteArray? {
|
||||||
val secretKey = maybeUserSecretKey() ?: return null
|
val secretKey = maybeUserSecretKey() ?: return null
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val localUserKey = storage.getUserPublicKey() ?: return null
|
|
||||||
val convoConfig = ConversationVolatileConfig.newInstance(secretKey)
|
val convoConfig = ConversationVolatileConfig.newInstance(secretKey)
|
||||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||||
threadDb.approvedConversationList.use { cursor ->
|
threadDb.approvedConversationList.use { cursor ->
|
||||||
@ -172,9 +172,18 @@ object ConfigurationMessageUtilities {
|
|||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
||||||
convoConfig.getOrConstructLegacyGroup(groupPublicKey)
|
convoConfig.getOrConstructLegacyGroup(groupPublicKey)
|
||||||
}
|
}
|
||||||
recipient.isContactRecipient -> convoConfig.getOrConstructOneToOne(recipient.address.serialize())
|
recipient.isContactRecipient -> {
|
||||||
|
val sessionId = SessionId(recipient.address.serialize())
|
||||||
|
|
||||||
|
if (recipient.isLocalNumber) null // this is handled by the user profile NTS data
|
||||||
|
else convoConfig.getOrConstructOneToOne(recipient.address.serialize())
|
||||||
|
}
|
||||||
else -> null
|
else -> null
|
||||||
} ?: continue
|
}
|
||||||
|
if (contact == null) {
|
||||||
|
current = reader.next
|
||||||
|
continue
|
||||||
|
}
|
||||||
contact.lastRead = current.lastSeen
|
contact.lastRead = current.lastSeen
|
||||||
contact.unread = false // TODO: make the forced unread work at DB level
|
contact.unread = false // TODO: make the forced unread work at DB level
|
||||||
convoConfig.set(contact)
|
convoConfig.set(contact)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 5a7569861d1b39d866ba7d8c7440db1908e84798
|
Subproject commit f76fee84d76bf0437e57a5e4ae15ba76a31e0ca6
|
@ -188,6 +188,7 @@ class InstrumentedTests {
|
|||||||
userProfile.setName("Kallie")
|
userProfile.setName("Kallie")
|
||||||
val newUserPic = UserPic("http://example.org/omg-pic-123.bmp", "secret78901234567890123456789012".encodeToByteArray())
|
val newUserPic = UserPic("http://example.org/omg-pic-123.bmp", "secret78901234567890123456789012".encodeToByteArray())
|
||||||
userProfile.setPic(newUserPic)
|
userProfile.setPic(newUserPic)
|
||||||
|
userProfile.setNtsPriority(9)
|
||||||
|
|
||||||
// Retrieve them just to make sure they set properly:
|
// Retrieve them just to make sure they set properly:
|
||||||
assertEquals("Kallie", userProfile.getName())
|
assertEquals("Kallie", userProfile.getName())
|
||||||
@ -205,20 +206,22 @@ class InstrumentedTests {
|
|||||||
Hex.fromStringCondensed("ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965")
|
Hex.fromStringCondensed("ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965")
|
||||||
|
|
||||||
val expectedPush1Decrypted = ("d" +
|
val expectedPush1Decrypted = ("d" +
|
||||||
"1:#" + "i1e"+
|
"1:#"+ "i1e" +
|
||||||
"1:&" + "d"+
|
"1:&"+ "d"+
|
||||||
"1:n" + "6:Kallie"+
|
"1:+"+ "i9e"+
|
||||||
"1:p" + "34:http://example.org/omg-pic-123.bmp"+
|
"1:n"+ "6:Kallie"+
|
||||||
"1:q" + "32:secret78901234567890123456789012"+
|
"1:p"+ "34:http://example.org/omg-pic-123.bmp"+
|
||||||
|
"1:q"+ "32:secret78901234567890123456789012"+
|
||||||
|
"e"+
|
||||||
|
"1:<"+ "l"+
|
||||||
|
"l"+ "i0e"+ "32:").encodeToByteArray() + expHash0 + ("de"+ "e"+
|
||||||
|
"e"+
|
||||||
|
"1:="+ "d"+
|
||||||
|
"1:+" +"0:"+
|
||||||
|
"1:n" +"0:"+
|
||||||
|
"1:p" +"0:"+
|
||||||
|
"1:q" +"0:"+
|
||||||
"e"+
|
"e"+
|
||||||
"1:<" + "l"+
|
|
||||||
"l" + "i0e" + "32:").encodeToByteArray() + expHash0 + ("de" + "e" +
|
|
||||||
"e" +
|
|
||||||
"1:=" + "d" +
|
|
||||||
"1:n" + "0:" +
|
|
||||||
"1:p" + "0:" +
|
|
||||||
"1:q" + "0:" +
|
|
||||||
"e" +
|
|
||||||
"e").encodeToByteArray()
|
"e").encodeToByteArray()
|
||||||
|
|
||||||
assertEquals(1, newSeqNo)
|
assertEquals(1, newSeqNo)
|
||||||
@ -227,19 +230,20 @@ class InstrumentedTests {
|
|||||||
// We did call push but we haven't confirmed it as stored yet, so this will still return true:
|
// We did call push but we haven't confirmed it as stored yet, so this will still return true:
|
||||||
assertTrue(userProfile.needsPush())
|
assertTrue(userProfile.needsPush())
|
||||||
|
|
||||||
userProfile.confirmPushed(newSeqNo, "fakehash1")
|
|
||||||
|
|
||||||
val dump = userProfile.dump()
|
val dump = userProfile.dump()
|
||||||
// (in a real client we'd now store this to disk)
|
// (in a real client we'd now store this to disk)
|
||||||
assertFalse(userProfile.needsDump())
|
assertFalse(userProfile.needsDump())
|
||||||
val expectedDump = ("d" +
|
val expectedDump = ("d" +
|
||||||
"1:!i2e" +
|
"1:!"+ "i2e" +
|
||||||
"1:$").encodeToByteArray() + expectedPush1Decrypted.size.toString().encodeToByteArray() +
|
"1:$").encodeToByteArray() + expectedPush1Decrypted.size.toString().encodeToByteArray() +
|
||||||
":".encodeToByteArray() + expectedPush1Decrypted +
|
":".encodeToByteArray() + expectedPush1Decrypted +
|
||||||
|
"1:(0:1:)le".encodeToByteArray()+
|
||||||
"e".encodeToByteArray()
|
"e".encodeToByteArray()
|
||||||
|
|
||||||
assertArrayEquals(expectedDump, dump)
|
assertArrayEquals(expectedDump, dump)
|
||||||
|
|
||||||
|
userProfile.confirmPushed(newSeqNo, "fakehash1")
|
||||||
|
|
||||||
val newConf = UserProfile.newInstance(edSk)
|
val newConf = UserProfile.newInstance(edSk)
|
||||||
|
|
||||||
val accepted = newConf.merge("fakehash1" to newToPush)
|
val accepted = newConf.merge("fakehash1" to newToPush)
|
||||||
@ -258,16 +262,16 @@ class InstrumentedTests {
|
|||||||
val conf = userProfile.push()
|
val conf = userProfile.push()
|
||||||
val conf2 = newConf.push()
|
val conf2 = newConf.push()
|
||||||
|
|
||||||
userProfile.confirmPushed(conf.seqNo, "fakehash1")
|
userProfile.confirmPushed(conf.seqNo, "fakehash2")
|
||||||
newConf.confirmPushed(conf2.seqNo, "fakehash2")
|
newConf.confirmPushed(conf2.seqNo, "fakehash3")
|
||||||
|
|
||||||
userProfile.dump()
|
userProfile.dump()
|
||||||
userProfile.dump()
|
userProfile.dump()
|
||||||
|
|
||||||
assertFalse(conf.config.contentEquals(conf2.config))
|
assertFalse(conf.config.contentEquals(conf2.config))
|
||||||
|
|
||||||
newConf.merge("fakehash1" to conf.config)
|
newConf.merge("fakehash2" to conf.config)
|
||||||
userProfile.merge("fakehash2" to conf2.config)
|
userProfile.merge("fakehash3" to conf2.config)
|
||||||
|
|
||||||
assertTrue(newConf.needsPush())
|
assertTrue(newConf.needsPush())
|
||||||
assertTrue(userProfile.needsPush())
|
assertTrue(userProfile.needsPush())
|
||||||
@ -276,20 +280,20 @@ class InstrumentedTests {
|
|||||||
|
|
||||||
assertEquals(3, newSeq1.seqNo)
|
assertEquals(3, newSeq1.seqNo)
|
||||||
|
|
||||||
userProfile.confirmPushed(newSeq1.seqNo, "fakehash3")
|
userProfile.confirmPushed(newSeq1.seqNo, "fakehash4")
|
||||||
|
|
||||||
// assume newConf push gets rejected as it was last to write and clear previous config by hash on oxenss
|
// assume newConf push gets rejected as it was last to write and clear previous config by hash on oxenss
|
||||||
newConf.merge("fakehash3" to newSeq1.config)
|
newConf.merge("fakehash4" to newSeq1.config)
|
||||||
|
|
||||||
val newSeqMerge = newConf.push()
|
val newSeqMerge = newConf.push()
|
||||||
|
|
||||||
newConf.confirmPushed(newSeqMerge.seqNo, "fakehash4")
|
newConf.confirmPushed(newSeqMerge.seqNo, "fakehash5")
|
||||||
|
|
||||||
assertEquals("Nibbler", newConf.getName())
|
assertEquals("Nibbler", newConf.getName())
|
||||||
assertEquals(4, newSeqMerge.seqNo)
|
assertEquals(4, newSeqMerge.seqNo)
|
||||||
|
|
||||||
// userProfile device polls and merges
|
// userProfile device polls and merges
|
||||||
userProfile.merge("fakehash4" to newSeqMerge.config)
|
userProfile.merge("fakehash5" to newSeqMerge.config)
|
||||||
|
|
||||||
|
|
||||||
val userConfigMerge = userProfile.push()
|
val userConfigMerge = userProfile.push()
|
||||||
|
@ -76,3 +76,17 @@ Java_network_loki_messenger_libsession_1util_UserProfile_setPic(JNIEnv *env, job
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsPriority(JNIEnv *env, jobject thiz,
|
||||||
|
jint priority) {
|
||||||
|
auto profile = ptrToProfile(env, thiz);
|
||||||
|
profile->set_nts_priority(priority);
|
||||||
|
}
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsHidden(JNIEnv *env, jobject thiz,
|
||||||
|
jboolean is_hidden) {
|
||||||
|
auto profile = ptrToProfile(env, thiz);
|
||||||
|
profile->set_nts_hidden(is_hidden);
|
||||||
|
}
|
@ -43,11 +43,6 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
|||||||
|
|
||||||
external fun free()
|
external fun free()
|
||||||
|
|
||||||
@Override
|
|
||||||
fun finalize() {
|
|
||||||
free()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Contacts(pointer: Long) : ConfigBase(pointer) {
|
class Contacts(pointer: Long) : ConfigBase(pointer) {
|
||||||
@ -98,6 +93,8 @@ class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
|||||||
external fun getName(): String?
|
external fun getName(): String?
|
||||||
external fun getPic(): UserPic
|
external fun getPic(): UserPic
|
||||||
external fun setPic(userPic: UserPic)
|
external fun setPic(userPic: UserPic)
|
||||||
|
external fun setNtsPriority(priority: Int)
|
||||||
|
external fun setNtsHidden(isHidden: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||||
|
Loading…
Reference in New Issue
Block a user