diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-05-23 10:05:58 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-05-23 10:05:58 -0300 |
| commit | 30d55fe3e013e2ef4fa01dce787ac0af781f2450 (patch) | |
| tree | d1697c4f72283c2a0e955f5b2ffe0e0c51dcca06 | |
| parent | 8ab37040fcc2e8ec0e70555608351e9f4aa01e2c (diff) | |
| parent | 48a7524589ad1f97a13c08a2a9b02541f89dbfe4 (diff) | |
| download | mullvadvpn-30d55fe3e013e2ef4fa01dce787ac0af781f2450.tar.xz mullvadvpn-30d55fe3e013e2ef4fa01dce787ac0af781f2450.zip | |
Merge branch 'fetch-relay-constraint-on-android'
8 files changed, 222 insertions, 6 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt index 043c8efe15..f2a5a5a97f 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt @@ -38,8 +38,7 @@ class LaunchFragment : Fragment() { private fun checkForAccountToken() = GlobalScope.async(Dispatchers.Default) { val parentActivity = activity as MainActivity - val daemon = parentActivity.asyncDaemon.await() - val settings = daemon.getSettings() + val settings = parentActivity.asyncSettings.await() settings.accountToken != null } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt index b68671afbd..6e3d34730b 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt @@ -12,6 +12,8 @@ import kotlinx.coroutines.Job import android.os.Bundle import android.support.v4.app.FragmentActivity +import net.mullvad.mullvadvpn.model.RelaySettings +import net.mullvad.mullvadvpn.model.Settings import net.mullvad.mullvadvpn.relaylist.RelayItem import net.mullvad.mullvadvpn.relaylist.RelayList @@ -27,8 +29,15 @@ class MainActivity : FragmentActivity() { val relayList: RelayList get() = runBlocking { asyncRelayList.await() } + var asyncSettings = fetchSettings() + private set + val settings + get() = runBlocking { asyncSettings.await() } + var selectedRelayItem: RelayItem? = null + private val restoreSelectedRelayListItemJob = restoreSelectedRelayListItem() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) @@ -41,6 +50,8 @@ class MainActivity : FragmentActivity() { } override fun onDestroy() { + restoreSelectedRelayListItemJob.cancel() + asyncSettings.cancel() asyncRelayList.cancel() asyncDaemon.cancel() @@ -63,4 +74,22 @@ class MainActivity : FragmentActivity() { private fun fetchRelayList() = GlobalScope.async(Dispatchers.Default) { RelayList(asyncDaemon.await().getRelayLocations()) } + + private fun fetchSettings() = GlobalScope.async(Dispatchers.Default) { + asyncDaemon.await().getSettings() + } + + private fun restoreSelectedRelayListItem() = GlobalScope.launch(Dispatchers.Default) { + val relaySettings = asyncSettings.await().relaySettings + + when (relaySettings) { + is RelaySettings.CustomTunnelEndpoint -> selectedRelayItem = null + is RelaySettings.RelayConstraints -> { + val location = relaySettings.location + val relayList = asyncRelayList.await() + + selectedRelayItem = relayList.findItemForLocation(location, true) + } + } + } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt new file mode 100644 index 0000000000..6fded8f9c5 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt @@ -0,0 +1,6 @@ +package net.mullvad.mullvadvpn.model + +sealed class RelaySettings { + class CustomTunnelEndpoint() : RelaySettings() + class RelayConstraints(var location: Constraint<LocationConstraint>) : RelaySettings() +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt index 1254492b57..c0c2abdbe7 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt @@ -1,4 +1,4 @@ package net.mullvad.mullvadvpn.model -data class Settings(var accountToken: String?) { +data class Settings(var accountToken: String?, var relaySettings: RelaySettings) { } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemHolder.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemHolder.kt index b67c31e2a9..e753d3af5a 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemHolder.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemHolder.kt @@ -65,6 +65,12 @@ class RelayItemHolder( if (item.hasChildren) { chevron.visibility = View.VISIBLE + + if (item.expanded) { + chevron.rotation = 180.0F + } else { + chevron.rotation = 0.0F + } } else { chevron.visibility = View.GONE } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayList.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayList.kt index 964833f675..809fa1265f 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayList.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayList.kt @@ -1,5 +1,8 @@ package net.mullvad.mullvadvpn.relaylist +import net.mullvad.mullvadvpn.model.Constraint +import net.mullvad.mullvadvpn.model.LocationConstraint + class RelayList { val countries: List<RelayCountry> @@ -16,4 +19,47 @@ class RelayList { RelayCountry(country.name, country.code, false, cities) } } + + fun findItemForLocation( + constraint: Constraint<LocationConstraint>, + expand: Boolean = false + ): RelayItem? { + when (constraint) { + is Constraint.Any -> return null + is Constraint.Only -> { + val location = constraint.value + + when (location) { + is LocationConstraint.Country -> { + return countries.find { country -> country.code == location.countryCode } + } + is LocationConstraint.City -> { + val country = countries.find { country -> + country.code == location.countryCode + } + + if (expand) { + country?.expanded = true + } + + return country?.cities?.find { city -> city.code == location.cityCode } + } + is LocationConstraint.Hostname -> { + val country = countries.find { country -> + country.code == location.countryCode + } + + val city = country?.cities?.find { city -> city.code == location.cityCode } + + if (expand) { + country?.expanded = true + city?.expanded = true + } + + return city?.relays?.find { relay -> relay.name == location.hostname } + } + } + } + } + } } diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs index 22b582bc1b..1c6733252b 100644 --- a/mullvad-jni/src/into_java.rs +++ b/mullvad-jni/src/into_java.rs @@ -6,9 +6,12 @@ use jni::{ }; use mullvad_types::{ account::AccountData, + relay_constraints::{Constraint, LocationConstraint, RelayConstraints, RelaySettings}, relay_list::{Relay, RelayList, RelayListCity, RelayListCountry}, settings::Settings, + CustomTunnelEndpoint, }; +use std::fmt::Debug; pub trait IntoJava<'env> { type JavaType; @@ -154,15 +157,140 @@ impl<'env> IntoJava<'env> for Relay { } } +impl<'env, T> IntoJava<'env> for Constraint<T> +where + T: Clone + Eq + Debug + IntoJava<'env>, + JObject<'env>: From<T::JavaType>, +{ + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + match self { + Constraint::Any => { + let class = get_class("net/mullvad/mullvadvpn/model/Constraint$Any"); + + env.new_object(&class, "()V", &[]) + .expect("Failed to create Constraint.Any Java object") + } + Constraint::Only(constraint) => { + let class = get_class("net/mullvad/mullvadvpn/model/Constraint$Only"); + let value = env.auto_local(JObject::from(constraint.into_java(env))); + let parameters = [JValue::Object(value.as_obj())]; + + env.new_object(&class, "(Ljava/lang/Object;)V", ¶meters) + .expect("Failed to create Constraint.Only Java object") + } + } + } +} + +impl<'env> IntoJava<'env> for LocationConstraint { + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + match self { + LocationConstraint::Country(country_code) => { + let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$Country"); + let country = env.auto_local(JObject::from(country_code.into_java(env))); + let parameters = [JValue::Object(country.as_obj())]; + + env.new_object(&class, "(Ljava/lang/String;)V", ¶meters) + .expect("Failed to create LocationConstraint.Country Java object") + } + LocationConstraint::City(country_code, city_code) => { + let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$City"); + let country = env.auto_local(JObject::from(country_code.into_java(env))); + let city = env.auto_local(JObject::from(city_code.into_java(env))); + let parameters = [ + JValue::Object(country.as_obj()), + JValue::Object(city.as_obj()), + ]; + + env.new_object( + &class, + "(Ljava/lang/String;Ljava/lang/String;)V", + ¶meters, + ) + .expect("Failed to create LocationConstraint.City Java object") + } + LocationConstraint::Hostname(country_code, city_code, hostname) => { + let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$Hostname"); + let country = env.auto_local(JObject::from(country_code.into_java(env))); + let city = env.auto_local(JObject::from(city_code.into_java(env))); + let hostname = env.auto_local(JObject::from(hostname.into_java(env))); + let parameters = [ + JValue::Object(country.as_obj()), + JValue::Object(city.as_obj()), + JValue::Object(hostname.as_obj()), + ]; + + env.new_object( + &class, + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", + ¶meters, + ) + .expect("Failed to create LocationConstraint.Hostname Java object") + } + } + } +} + +impl<'env> IntoJava<'env> for RelaySettings { + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + match self { + RelaySettings::CustomTunnelEndpoint(endpoint) => endpoint.into_java(env), + RelaySettings::Normal(relay_constraints) => relay_constraints.into_java(env), + } + } +} + +impl<'env> IntoJava<'env> for CustomTunnelEndpoint { + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + let class = get_class("net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint"); + + env.new_object(&class, "()V", &[]) + .expect("Failed to create CustomTunnelEndpoint Java object") + } +} + +impl<'env> IntoJava<'env> for RelayConstraints { + type JavaType = JObject<'env>; + + fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { + let class = get_class("net/mullvad/mullvadvpn/model/RelaySettings$RelayConstraints"); + let location = env.auto_local(self.location.into_java(env)); + let parameters = [JValue::Object(location.as_obj())]; + + env.new_object( + &class, + "(Lnet/mullvad/mullvadvpn/model/Constraint;)V", + ¶meters, + ) + .expect("Failed to create RelaySettings.RelayConstraints Java object") + } +} + impl<'env> IntoJava<'env> for Settings { type JavaType = JObject<'env>; fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { let class = get_class("net/mullvad/mullvadvpn/model/Settings"); let account_token = env.auto_local(JObject::from(self.get_account_token().into_java(env))); - let parameters = [JValue::Object(account_token.as_obj())]; + let relay_settings = env.auto_local(self.get_relay_settings().into_java(env)); + let parameters = [ + JValue::Object(account_token.as_obj()), + JValue::Object(relay_settings.as_obj()), + ]; - env.new_object(&class, "(Ljava/lang/String;)V", ¶meters) - .expect("Failed to create Settings Java object") + env.new_object( + &class, + "(Ljava/lang/String;Lnet/mullvad/mullvadvpn/model/RelaySettings;)V", + ¶meters, + ) + .expect("Failed to create Settings Java object") } } diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index 99a3041d9a..9a7f81a0fc 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -31,6 +31,8 @@ const CLASSES_TO_LOAD: &[&str] = &[ "net/mullvad/mullvadvpn/model/RelayList", "net/mullvad/mullvadvpn/model/RelayListCity", "net/mullvad/mullvadvpn/model/RelayListCountry", + "net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint", + "net/mullvad/mullvadvpn/model/RelaySettings$RelayConstraints", "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint", "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$RelayConstraintsUpdate", "net/mullvad/mullvadvpn/model/Settings", |
