diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index cfdc16e06c4..daa159501b7 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.stopTimedVersionCheck(); 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/VersionDataFetcher.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt new file mode 100644 index 00000000000..aba814524c8 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionDataFetcher.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt deleted file mode 100644 index 76075b4ac16..00000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ /dev/null @@ -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") - } - } - } -} \ 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..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 @@ -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,