diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-07-31 08:44:24 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-07-31 08:44:24 -0300 |
| commit | bb151cecadf612fd6028288f25568d312b9fbeb3 (patch) | |
| tree | f858981795d3ec8b12ef2cae387df61e01ba79dd | |
| parent | 5317e5cc9d617e05088918531288b8f2ef103b73 (diff) | |
| parent | a4a40ab5efce535ec42c7201dcddd89fc929072a (diff) | |
| download | mullvadvpn-bb151cecadf612fd6028288f25568d312b9fbeb3.tar.xz mullvadvpn-bb151cecadf612fd6028288f25568d312b9fbeb3.zip | |
Merge branch 'check-for-new-version'
7 files changed, 143 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt index 9de3dc12d7..751334ea61 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt @@ -1,6 +1,7 @@ package net.mullvad.mullvadvpn import net.mullvad.mullvadvpn.model.AccountData +import net.mullvad.mullvadvpn.model.AppVersionInfo import net.mullvad.mullvadvpn.model.GeoIpLocation import net.mullvad.mullvadvpn.model.KeygenEvent import net.mullvad.mullvadvpn.model.PublicKey @@ -29,6 +30,7 @@ class MullvadDaemon(val vpnService: MullvadVpnService) { external fun getRelayLocations(): RelayList external fun getSettings(): Settings external fun getState(): TunnelState + external fun getVersionInfo(): AppVersionInfo? external fun getWireguardKey(): PublicKey? external fun setAccount(accountToken: String?) external fun updateRelaySettings(update: RelaySettingsUpdate) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt index bc0c317cf2..6cb45329ff 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt @@ -15,15 +15,19 @@ import android.net.VpnService import android.os.Binder import android.os.IBinder +import net.mullvad.mullvadvpn.dataproxy.AppVersionInfoFetcher import net.mullvad.mullvadvpn.model.TunConfig class MullvadVpnService : VpnService() { private val created = CompletableDeferred<Unit>() private val binder = LocalBinder() + private lateinit var versionInfoFetcher: AppVersionInfoFetcher + val daemon = startDaemon() override fun onCreate() { + versionInfoFetcher = AppVersionInfoFetcher(daemon, this) created.complete(Unit) } @@ -32,6 +36,7 @@ class MullvadVpnService : VpnService() { } override fun onDestroy() { + versionInfoFetcher.stop() daemon.cancel() created.cancel() } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoFetcher.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoFetcher.kt new file mode 100644 index 0000000000..2b066c934b --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoFetcher.kt @@ -0,0 +1,74 @@ +package net.mullvad.mullvadvpn.dataproxy + +import java.util.Calendar + +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope + +import android.content.Context + +import net.mullvad.mullvadvpn.MullvadDaemon + +val ONE_DAY_IN_MILLISECONDS = 24L * 60L * 60L * 1000L +val ONE_MINUTE_IN_MILLISECONDS = 60L * 1000L + +val KEY_CURRENT_IS_SUPPORTED = "current_is_supported" +val KEY_LAST_UPDATED = "last_updated" +val KEY_LATEST_STABLE = "latest_stable" +val KEY_LATEST = "latest" +val SHARED_PREFERENCES = "app_version_info_cache" + +class AppVersionInfoFetcher(val daemon: Deferred<MullvadDaemon>, val context: Context) { + private val preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE) + + private val mainLoop = run() + + fun stop() { + mainLoop.cancel() + } + + private fun run() = GlobalScope.launch(Dispatchers.Default) { + while (true) { + delay(calculateDelay()) + fetch() + } + } + + private fun calculateDelay(): Long { + val now = Calendar.getInstance().timeInMillis + val lastUpdated = preferences.getLong(KEY_LAST_UPDATED, 0) + val delta = now - lastUpdated + + if (delta < 0 || delta >= ONE_DAY_IN_MILLISECONDS) { + return 0 + } else { + return ONE_DAY_IN_MILLISECONDS - delta + } + } + + private suspend fun fetch() { + var now = Calendar.getInstance().timeInMillis + var versionInfo = daemon.await().getVersionInfo() + var attempt = 0 + + while (attempt < 5 && versionInfo == null) { + delay(ONE_MINUTE_IN_MILLISECONDS) + now = Calendar.getInstance().timeInMillis + versionInfo = daemon.await().getVersionInfo() + attempt += 1 + } + + if (versionInfo != null) { + preferences.edit().apply { + putLong(KEY_LAST_UPDATED, now) + putBoolean(KEY_CURRENT_IS_SUPPORTED, versionInfo.currentIsSupported) + putString(KEY_LATEST_STABLE, versionInfo.latestStable) + putString(KEY_LATEST, versionInfo.latest) + commit() + } + } + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt new file mode 100644 index 0000000000..0c41090f3f --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/AppVersionInfo.kt @@ -0,0 +1,7 @@ +package net.mullvad.mullvadvpn.model + +data class AppVersionInfo( + val currentIsSupported: Boolean, + val latestStable: String, + val latest: String +) diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs index 9cada243af..5ba890f90d 100644 --- a/mullvad-jni/src/daemon_interface.rs +++ b/mullvad-jni/src/daemon_interface.rs @@ -7,6 +7,7 @@ use mullvad_types::{ relay_list::RelayList, settings::Settings, states::{TargetState, TunnelState}, + version::AppVersionInfo, wireguard::KeygenEvent, }; use parking_lot::Mutex; @@ -128,6 +129,17 @@ impl DaemonInterface { Ok(rx.wait().map_err(|_| Error::NoResponse)?) } + pub fn get_version_info(&self) -> Result<AppVersionInfo> { + let (tx, rx) = oneshot::channel(); + + self.send_command(ManagementCommand::GetVersionInfo(tx))?; + + rx.wait() + .map_err(|_| Error::NoResponse)? + .wait() + .map_err(Error::RpcError) + } + pub fn get_wireguard_key(&self) -> Result<Option<wireguard::PublicKey>> { let (tx, rx) = oneshot::channel(); diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs index fd5dbc8427..52aa9e2f7c 100644 --- a/mullvad-jni/src/into_java.rs +++ b/mullvad-jni/src/into_java.rs @@ -13,6 +13,7 @@ use mullvad_types::{ relay_list::{Relay, RelayList, RelayListCity, RelayListCountry}, settings::Settings, states::TunnelState, + version::AppVersionInfo, wireguard::KeygenEvent, CustomTunnelEndpoint, }; @@ -187,6 +188,29 @@ impl<'env> IntoJava<'env> for PublicKey { } } +impl<'env> IntoJava<'env> for AppVersionInfo { + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + let class = get_class("net/mullvad/mullvadvpn/model/AppVersionInfo"); + let current_is_supported = self.current_is_supported as jboolean; + let latest_stable = env.auto_local(*self.latest_stable.into_java(env)); + let latest = env.auto_local(*self.latest.into_java(env)); + let parameters = [ + JValue::Bool(current_is_supported), + JValue::Object(latest_stable.as_obj()), + JValue::Object(latest.as_obj()), + ]; + + env.new_object( + &class, + "(ZLjava/lang/String;Ljava/lang/String;)V", + ¶meters, + ) + .expect("Failed to create AppVersionInfo Java object") + } +} + impl<'env> IntoJava<'env> for AccountData { type JavaType = JObject<'env>; diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index 7b56831ee7..31d9cdf670 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -37,6 +37,7 @@ const CLASSES_TO_LOAD: &[&str] = &[ "net/mullvad/mullvadvpn/model/ActionAfterDisconnect$Block", "net/mullvad/mullvadvpn/model/ActionAfterDisconnect$Nothing", "net/mullvad/mullvadvpn/model/ActionAfterDisconnect$Reconnect", + "net/mullvad/mullvadvpn/model/AppVersionInfo", "net/mullvad/mullvadvpn/model/Constraint$Any", "net/mullvad/mullvadvpn/model/Constraint$Only", "net/mullvad/mullvadvpn/model/GeoIpLocation", @@ -366,6 +367,24 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getState<'env, #[no_mangle] #[allow(non_snake_case)] +pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getVersionInfo<'env, 'this>( + env: JNIEnv<'env>, + _: JObject<'this>, +) -> JObject<'env> { + match DAEMON_INTERFACE.get_version_info() { + Ok(version_info) => version_info.into_java(&env), + Err(error) => { + log::error!( + "{}", + error.display_chain_with_msg("Failed to get version information") + ); + JObject::null() + } + } +} + +#[no_mangle] +#[allow(non_snake_case)] pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getWireguardKey<'env, 'this>( env: JNIEnv<'env>, _: JObject<'this>, |
