From 7fa3d9f3ff5311bbcb7b535ab22ca96798efa259 Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Wed, 31 Jul 2024 13:53:54 +0930 Subject: [PATCH 1/5] Fix version check --- .../securesms/ApplicationContext.java | 12 ++-- .../manager/CreateAccountManager.kt | 4 ++ .../onboarding/manager/LoadAccountManager.kt | 6 +- .../{VersionUtil.kt => VersionDataFetcher.kt} | 56 +++++++++---------- .../messaging/file_server/FileServerApi.kt | 4 +- 5 files changed, 41 insertions(+), 41 deletions(-) rename app/src/main/java/org/thoughtcrime/securesms/util/{VersionUtil.kt => VersionDataFetcher.kt} (50%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index cfdc16e06c4..a50e003c655 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -86,7 +86,7 @@ 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 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 void onCreate() { 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 void onStart(@NonNull LifecycleOwner owner) { }); // fetch last version data - versionUtil.startTimedVersionCheck(); + versionDataFetcher.startTimedVersionCheck(); } @Override @@ -292,14 +290,14 @@ public void onStop(@NonNull LifecycleOwner owner) { poller.stopIfNeeded(); } ClosedGroupPollerV2.getShared().stopAll(); - versionUtil.stopTimedVersionCheck(); + versionDataFetcher.stopTimedVersionCheck(); } @Override public void onTerminate() { stopKovenant(); // Loki OpenGroupManager.INSTANCE.stopPolling(); - versionUtil.clear(); + versionDataFetcher.clear(); super.onTerminate(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt index 1e0a21d571f..98e9c8b20dd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt @@ -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() } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt index 5a401038305..51d1b24609c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt @@ -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() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt similarity index 50% rename from app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt rename to app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt index 76075b4ac16..48be478c95e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -4,33 +4,36 @@ 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 +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.time.Duration.Companion.hours -class VersionUtil( +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 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 runnable = Runnable { + fetchVersionData() + } private val scope = CoroutineScope(Dispatchers.Default) - private var job: Job? = null - - init { - runnable = Runnable { - fetchAndScheduleNextVersionCheck() - } - } fun startTimedVersionCheck() { - handler.post(runnable) + stopTimedVersionCheck() + + // Call immediately if 4h or more has elapsed since the last successful check else schedule. + handler.postDelayed( + runnable, + REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis() + ) } fun stopTimedVersionCheck() { @@ -38,31 +41,22 @@ class VersionUtil( } 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 { + scope.launch { try { - // perform the version check + // 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") + // We can silently ignore the error + Log.e(TAG, "Error fetching version data", e) } + + prefs.setLastVersionCheck() + startTimedVersionCheck() } } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt index fb9c014a15f..a5ebdd5d368 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt @@ -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,7 +127,7 @@ 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 From 40db23d341ff7a1e4a40a6199966df05b17b0b74 Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Wed, 31 Jul 2024 15:52:38 +0930 Subject: [PATCH 2/5] Fix setLastVersion called onException --- .../securesms/ApplicationContext.java | 2 +- .../securesms/util/VersionDataFetcher.kt | 49 ++++++++----------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index a50e003c655..daa159501b7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -297,7 +297,7 @@ public void onStop(@NonNull LifecycleOwner owner) { public void onTerminate() { stopKovenant(); // Loki OpenGroupManager.INSTANCE.stopPolling(); - versionDataFetcher.clear(); + versionDataFetcher.stopTimedVersionCheck(); super.onTerminate(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt index 48be478c95e..2868e4e8db9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -20,43 +20,36 @@ class VersionDataFetcher @Inject constructor( private val prefs: TextSecurePreferences ) { private val handler = Handler(Looper.getMainLooper()) - private val runnable = Runnable { - fetchVersionData() - } - - private val scope = CoroutineScope(Dispatchers.Default) - - fun startTimedVersionCheck() { - stopTimedVersionCheck() - - // Call immediately if 4h or more has elapsed since the last successful check else schedule. - handler.postDelayed( - runnable, - REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis() - ) - } - - fun stopTimedVersionCheck() { - handler.removeCallbacks(runnable) - } - - fun clear() { - stopTimedVersionCheck() - } - - private fun fetchVersionData() { + 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) } - - prefs.setLastVersionCheck() - startTimedVersionCheck() } } + + private val scope = CoroutineScope(Dispatchers.Default) + + fun startTimedVersionCheck( + delayMillis: Long = REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis() + ) { + stopTimedVersionCheck() + + // Call immediately if 4h or more has elapsed since the last successful check else schedule. + handler.postDelayed(fetchVersionData, delayMillis) + } + + fun stopTimedVersionCheck() { + handler.removeCallbacks(fetchVersionData) + } } \ No newline at end of file From 4992123bafcd2a40a9f5b5c4e822f87a57b0ff6f Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Wed, 31 Jul 2024 16:00:23 +0930 Subject: [PATCH 3/5] Cleanup comment --- .../org/thoughtcrime/securesms/util/VersionDataFetcher.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt index 2868e4e8db9..20f8ca53087 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -40,12 +40,16 @@ class VersionDataFetcher @Inject constructor( private val scope = CoroutineScope(Dispatchers.Default) + /** + * Schedules fetching version data [delayMillis] milliseconds from now. + * + * This method will fetch immediately if 4 hours or more has elapsed since the last successful + * check. + */ fun startTimedVersionCheck( delayMillis: Long = REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis() ) { stopTimedVersionCheck() - - // Call immediately if 4h or more has elapsed since the last successful check else schedule. handler.postDelayed(fetchVersionData, delayMillis) } From 72d77a9caf11df94e0e385206fffec8b9f3d8c4f Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Wed, 31 Jul 2024 17:40:47 +0930 Subject: [PATCH 4/5] Add @JvmOverloads --- .../java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt index 20f8ca53087..77588c21be7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -46,6 +46,7 @@ class VersionDataFetcher @Inject constructor( * This method will fetch immediately if 4 hours or more has elapsed since the last successful * check. */ + @JvmOverloads fun startTimedVersionCheck( delayMillis: Long = REFRESH_TIME_MS + prefs.getLastVersionCheck() - System.currentTimeMillis() ) { From 5c4e95c4ec66abb2ef3387732204be690c158368 Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Thu, 1 Aug 2024 10:34:45 +0930 Subject: [PATCH 5/5] Update VersionDataFetcher KDoc --- .../org/thoughtcrime/securesms/util/VersionDataFetcher.kt | 6 +++--- .../libsession/messaging/file_server/FileServerApi.kt | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt index 77588c21be7..aba814524c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -41,10 +41,10 @@ class VersionDataFetcher @Inject constructor( private val scope = CoroutineScope(Dispatchers.Default) /** - * Schedules fetching version data [delayMillis] milliseconds from now. + * Schedules fetching version data. * - * This method will fetch immediately if 4 hours or more has elapsed since the last successful - * check. + * @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( diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt index a5ebdd5d368..6a9c95aa561 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt @@ -131,10 +131,7 @@ object FileServerApi { 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,