|
|
@ -52,8 +52,11 @@ import org.thoughtcrime.securesms.database.ConfigDatabase
|
|
|
|
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
|
|
|
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
|
|
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
|
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
|
|
import org.thoughtcrime.securesms.groups.GroupManager
|
|
|
|
import org.thoughtcrime.securesms.groups.GroupManager
|
|
|
|
|
|
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Singleton
|
|
|
|
import javax.inject.Singleton
|
|
|
|
|
|
|
|
import kotlin.concurrent.read
|
|
|
|
|
|
|
|
import kotlin.concurrent.write
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Singleton
|
|
|
|
@Singleton
|
|
|
@ -78,8 +81,8 @@ class ConfigFactory @Inject constructor(
|
|
|
|
System.loadLibrary("session_util")
|
|
|
|
System.loadLibrary("session_util")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private val userConfigs = HashMap<AccountId, UserConfigsImpl>()
|
|
|
|
private val userConfigs = HashMap<AccountId, Pair<ReentrantReadWriteLock, UserConfigsImpl>>()
|
|
|
|
private val groupConfigs = HashMap<AccountId, GroupConfigsImpl>()
|
|
|
|
private val groupConfigs = HashMap<AccountId, Pair<ReentrantReadWriteLock, GroupConfigsImpl>>()
|
|
|
|
|
|
|
|
|
|
|
|
private val _configUpdateNotifications = MutableSharedFlow<ConfigUpdateNotification>(
|
|
|
|
private val _configUpdateNotifications = MutableSharedFlow<ConfigUpdateNotification>(
|
|
|
|
extraBufferCapacity = 5, // The notifications are normally important so we can afford to buffer a few
|
|
|
|
extraBufferCapacity = 5, // The notifications are normally important so we can afford to buffer a few
|
|
|
@ -97,21 +100,39 @@ class ConfigFactory @Inject constructor(
|
|
|
|
"No logged in user"
|
|
|
|
"No logged in user"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun <T> withUserConfigs(cb: (UserConfigs) -> T): T {
|
|
|
|
private fun ensureUserConfigsInitialized(): Pair<ReentrantReadWriteLock, UserConfigsImpl> {
|
|
|
|
val userAccountId = requiresCurrentUserAccountId()
|
|
|
|
val userAccountId = requiresCurrentUserAccountId()
|
|
|
|
val configs = synchronized(userConfigs) {
|
|
|
|
|
|
|
|
|
|
|
|
return synchronized(userConfigs) {
|
|
|
|
userConfigs.getOrPut(userAccountId) {
|
|
|
|
userConfigs.getOrPut(userAccountId) {
|
|
|
|
UserConfigsImpl(
|
|
|
|
ReentrantReadWriteLock() to UserConfigsImpl(
|
|
|
|
requiresCurrentUserED25519SecKey(),
|
|
|
|
userEd25519SecKey = requiresCurrentUserED25519SecKey(),
|
|
|
|
userAccountId,
|
|
|
|
userAccountId = userAccountId,
|
|
|
|
threadDb = threadDb,
|
|
|
|
threadDb = threadDb,
|
|
|
|
configDatabase = configDatabase,
|
|
|
|
configDatabase = configDatabase,
|
|
|
|
storage = storage.get()
|
|
|
|
storage = storage.get()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun ensureGroupConfigsInitialized(groupId: AccountId): Pair<ReentrantReadWriteLock, GroupConfigsImpl> {
|
|
|
|
|
|
|
|
val groupAdminKey = getClosedGroup(groupId)?.adminKey
|
|
|
|
|
|
|
|
return synchronized(groupConfigs) {
|
|
|
|
|
|
|
|
groupConfigs.getOrPut(groupId) {
|
|
|
|
|
|
|
|
ReentrantReadWriteLock() to GroupConfigsImpl(
|
|
|
|
|
|
|
|
userEd25519SecKey = requiresCurrentUserED25519SecKey(),
|
|
|
|
|
|
|
|
groupAccountId = groupId,
|
|
|
|
|
|
|
|
groupAdminKey = groupAdminKey,
|
|
|
|
|
|
|
|
configDatabase = configDatabase
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return synchronized(configs) {
|
|
|
|
override fun <T> withUserConfigs(cb: (UserConfigs) -> T): T {
|
|
|
|
|
|
|
|
val (lock, configs) = ensureUserConfigsInitialized()
|
|
|
|
|
|
|
|
return lock.read {
|
|
|
|
cb(configs)
|
|
|
|
cb(configs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -122,8 +143,9 @@ class ConfigFactory @Inject constructor(
|
|
|
|
* @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed.
|
|
|
|
* @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, Boolean>): T {
|
|
|
|
private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, Boolean>): T {
|
|
|
|
val (result, changed) = withUserConfigs { configs ->
|
|
|
|
val (lock, configs) = ensureUserConfigsInitialized()
|
|
|
|
cb(configs as UserConfigsImpl)
|
|
|
|
val (result, changed) = lock.write {
|
|
|
|
|
|
|
|
cb(configs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
if (changed) {
|
|
|
@ -160,25 +182,9 @@ class ConfigFactory @Inject constructor(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun <T> withGroupConfigs(groupId: AccountId, cb: (GroupConfigs) -> T): T {
|
|
|
|
override fun <T> withGroupConfigs(groupId: AccountId, cb: (GroupConfigs) -> T): T {
|
|
|
|
val groupAdminKey = getClosedGroup(groupId)?.adminKey
|
|
|
|
val (lock, configs) = ensureGroupConfigsInitialized(groupId)
|
|
|
|
|
|
|
|
|
|
|
|
val configs = synchronized(groupConfigs) {
|
|
|
|
|
|
|
|
var value = groupConfigs[groupId]
|
|
|
|
|
|
|
|
if (value == null || value.groupKeys.admin() != (groupAdminKey != null)) {
|
|
|
|
|
|
|
|
// No existing configs or existing configs have different admin settings with what we currently have
|
|
|
|
|
|
|
|
// Create a new group configs
|
|
|
|
|
|
|
|
value = GroupConfigsImpl(
|
|
|
|
|
|
|
|
requiresCurrentUserED25519SecKey(),
|
|
|
|
|
|
|
|
groupId,
|
|
|
|
|
|
|
|
groupAdminKey,
|
|
|
|
|
|
|
|
configDatabase
|
|
|
|
|
|
|
|
).also { groupConfigs[groupId] = it }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value
|
|
|
|
return lock.read {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return synchronized(configs) {
|
|
|
|
|
|
|
|
cb(configs)
|
|
|
|
cb(configs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -188,11 +194,14 @@ class ConfigFactory @Inject constructor(
|
|
|
|
recreateConfigInstances: Boolean,
|
|
|
|
recreateConfigInstances: Boolean,
|
|
|
|
cb: (GroupConfigsImpl) -> Pair<T, Boolean>): T {
|
|
|
|
cb: (GroupConfigsImpl) -> Pair<T, Boolean>): T {
|
|
|
|
if (recreateConfigInstances) {
|
|
|
|
if (recreateConfigInstances) {
|
|
|
|
groupConfigs.remove(groupId)
|
|
|
|
synchronized(groupConfigs) {
|
|
|
|
|
|
|
|
groupConfigs.remove(groupId)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
val (result, changed) = withGroupConfigs(groupId) { configs ->
|
|
|
|
val (lock, configs) = ensureGroupConfigsInitialized(groupId)
|
|
|
|
cb(configs as GroupConfigsImpl)
|
|
|
|
val (result, changed) = lock.write {
|
|
|
|
|
|
|
|
cb(configs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
if (changed) {
|
|
|
|