Merge pull request #1585 from bemusementpark/fix-version-check

Fix version check
This commit is contained in:
ThomasSession 2024-08-01 17:05:54 +10:00 committed by GitHub
commit 0616e148cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 77 additions and 82 deletions

View File

@ -86,7 +86,7 @@ import org.thoughtcrime.securesms.sskenvironment.ProfileManager;
import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager;
import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository;
import org.thoughtcrime.securesms.util.Broadcaster;
import org.thoughtcrime.securesms.util.VersionUtil;
import org.thoughtcrime.securesms.util.VersionDataFetcher;
import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper;
import org.thoughtcrime.securesms.webrtc.CallMessageProcessor;
import org.webrtc.PeerConnectionFactory;
@ -111,7 +111,6 @@ import javax.inject.Inject;
import dagger.hilt.EntryPoints;
import dagger.hilt.android.HiltAndroidApp;
import kotlin.Unit;
import kotlinx.coroutines.Job;
import network.loki.messenger.BuildConfig;
import network.loki.messenger.libsession_util.ConfigBase;
import network.loki.messenger.libsession_util.UserProfile;
@ -143,7 +142,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private HandlerThread conversationListHandlerThread;
private Handler conversationListHandler;
private PersistentLogger persistentLogger;
private VersionUtil versionUtil;
@Inject LokiAPIDatabase lokiAPIDatabase;
@Inject public Storage storage;
@ -153,6 +151,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject PushRegistry pushRegistry;
@Inject ConfigFactory configFactory;
@Inject LastSentTimestampCache lastSentTimestampCache;
@Inject VersionDataFetcher versionDataFetcher;
CallMessageProcessor callMessageProcessor;
MessagingModuleConfiguration messagingModuleConfiguration;
@ -250,7 +249,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
resubmitProfilePictureIfNeeded();
loadEmojiSearchIndexIfNeeded();
EmojiSource.refresh();
versionUtil = new VersionUtil(textSecurePreferences);
NetworkConstraint networkConstraint = new NetworkConstraint.Factory(this).create();
HTTP.INSTANCE.setConnectedToNetwork(networkConstraint::isMet);
@ -279,7 +277,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
});
// fetch last version data
versionUtil.startTimedVersionCheck();
versionDataFetcher.startTimedVersionCheck();
}
@Override
@ -292,14 +290,14 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
poller.stopIfNeeded();
}
ClosedGroupPollerV2.getShared().stopAll();
versionUtil.stopTimedVersionCheck();
versionDataFetcher.stopTimedVersionCheck();
}
@Override
public void onTerminate() {
stopKovenant(); // Loki
OpenGroupManager.INSTANCE.stopPolling();
versionUtil.clear();
versionDataFetcher.stopTimedVersionCheck();
super.onTerminate();
}

View File

@ -8,6 +8,7 @@ import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.hexEncodedPublicKey
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.util.VersionDataFetcher
import javax.inject.Inject
import javax.inject.Singleton
@ -16,6 +17,7 @@ class CreateAccountManager @Inject constructor(
private val application: Application,
private val prefs: TextSecurePreferences,
private val configFactory: ConfigFactory,
private val versionDataFetcher: VersionDataFetcher
) {
private val database: LokiAPIDatabaseProtocol
get() = SnodeModule.shared.storage
@ -41,5 +43,7 @@ class CreateAccountManager @Inject constructor(
prefs.setLocalRegistrationId(registrationID)
prefs.setLocalNumber(userHexEncodedPublicKey)
prefs.setRestorationTime(0)
versionDataFetcher.startTimedVersionCheck()
}
}

View File

@ -12,6 +12,7 @@ import org.session.libsignal.utilities.hexEncodedPublicKey
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.util.VersionDataFetcher
import javax.inject.Inject
import javax.inject.Singleton
@ -19,7 +20,8 @@ import javax.inject.Singleton
class LoadAccountManager @Inject constructor(
@dagger.hilt.android.qualifiers.ApplicationContext private val context: Context,
private val configFactory: ConfigFactory,
private val prefs: TextSecurePreferences
private val prefs: TextSecurePreferences,
private val versionDataFetcher: VersionDataFetcher
) {
private val database: LokiAPIDatabaseProtocol
get() = SnodeModule.shared.storage
@ -52,6 +54,8 @@ class LoadAccountManager @Inject constructor(
setHasViewedSeed(true)
}
versionDataFetcher.startTimedVersionCheck()
ApplicationContext.getInstance(context).retrieveUserProfile()
}
}

View File

@ -0,0 +1,60 @@
package org.thoughtcrime.securesms.util
import android.os.Handler
import android.os.Looper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.session.libsession.messaging.file_server.FileServerApi
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.time.Duration.Companion.hours
private val TAG: String = VersionDataFetcher::class.java.simpleName
private val REFRESH_TIME_MS = 4.hours.inWholeMilliseconds
@Singleton
class VersionDataFetcher @Inject constructor(
private val prefs: TextSecurePreferences
) {
private val handler = Handler(Looper.getMainLooper())
private val fetchVersionData = Runnable {
scope.launch {
try {
// Perform the version check
val clientVersion = FileServerApi.getClientVersion()
Log.i(TAG, "Fetched version data: $clientVersion")
prefs.setLastVersionCheck()
startTimedVersionCheck()
} catch (e: Exception) {
// We can silently ignore the error
Log.e(TAG, "Error fetching version data", e)
// Schedule the next check for 4 hours from now, but do not setLastVersionCheck
// so the app will retry when the app is next foregrounded.
startTimedVersionCheck(REFRESH_TIME_MS)
}
}
}
private val scope = CoroutineScope(Dispatchers.Default)
/**
* Schedules fetching version data.
*
* @param delayMillis The delay before fetching version data. Default value is 4 hours from the
* last check or 0 if there was no previous check or if it was longer than 4 hours ago.
*/
@JvmOverloads
fun startTimedVersionCheck(
delayMillis: Long = REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis()
) {
stopTimedVersionCheck()
handler.postDelayed(fetchVersionData, delayMillis)
}
fun stopTimedVersionCheck() {
handler.removeCallbacks(fetchVersionData)
}
}

View File

@ -1,68 +0,0 @@
package org.thoughtcrime.securesms.util
import android.os.Handler
import android.os.Looper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.session.libsession.messaging.file_server.FileServerApi
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import java.util.concurrent.TimeUnit
class VersionUtil(
private val prefs: TextSecurePreferences
) {
private val TAG: String = VersionUtil::class.java.simpleName
private val FOUR_HOURS: Long = TimeUnit.HOURS.toMillis(4)
private val handler = Handler(Looper.getMainLooper())
private val runnable: Runnable
private val scope = CoroutineScope(Dispatchers.Default)
private var job: Job? = null
init {
runnable = Runnable {
fetchAndScheduleNextVersionCheck()
}
}
fun startTimedVersionCheck() {
handler.post(runnable)
}
fun stopTimedVersionCheck() {
handler.removeCallbacks(runnable)
}
fun clear() {
job?.cancel()
stopTimedVersionCheck()
}
private fun fetchAndScheduleNextVersionCheck() {
fetchVersionData()
handler.postDelayed(runnable, FOUR_HOURS)
}
private fun fetchVersionData() {
// only perform this if at least 4h has elapsed since th last successful check
val lastCheck = System.currentTimeMillis() - prefs.getLastVersionCheck()
if (lastCheck < FOUR_HOURS) return
job?.cancel()
job = scope.launch {
try {
// perform the version check
val clientVersion = FileServerApi.getClientVersion()
Log.i(TAG, "Fetched version data: $clientVersion")
prefs.setLastVersionCheck()
} catch (e: Exception) {
// we can silently ignore the error
Log.e(TAG, "Error fetching version data: $e")
}
}
}
}

View File

@ -16,7 +16,7 @@ import org.session.libsignal.utilities.HTTP
import org.session.libsignal.utilities.JsonUtil
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.toHexString
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.milliseconds
object FileServerApi {
@ -127,14 +127,11 @@ object FileServerApi {
?: throw (Error.NoEd25519KeyPair)
val blindedKeys = BlindKeyAPI.blindVersionKeyPair(secretKey)
val timestamp = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) // The current timestamp in seconds
val timestamp = System.currentTimeMillis().milliseconds.inWholeSeconds // The current timestamp in seconds
val signature = BlindKeyAPI.blindVersionSign(secretKey, timestamp)
// The hex encoded version-blinded public key with a 07 prefix
val blindedPkHex = buildString {
append("07")
append(blindedKeys.pubKey.toHexString())
}
val blindedPkHex = "07" + blindedKeys.pubKey.toHexString()
val request = Request(
verb = HTTP.Verb.GET,