summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt8
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryAdapter.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryHolder.kt5
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt13
-rw-r--r--android/src/main/res/drawable/account_history_remove.xml8
-rw-r--r--android/src/main/res/drawable/account_history_remove_normal.xml38
-rw-r--r--android/src/main/res/drawable/account_history_remove_pressed.xml38
-rw-r--r--android/src/main/res/layout/account_history_entry.xml15
-rw-r--r--mullvad-jni/src/daemon_interface.rs8
-rw-r--r--mullvad-jni/src/lib.rs22
13 files changed, 163 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3385e58dca..014320e2ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,7 @@ Line wrap the file at 100 chars. Th
#### Android
- Removed the Quit button.
+- Add button to remove account and WireGuard key from history in the login screen.
### Fixed
- Stop resetting the firewall after an upgrade to not leak after an upgrade.
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
index 6154956610..55342ea166 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt
@@ -90,6 +90,13 @@ class AccountCache(val daemon: MullvadDaemon, val settingsListener: SettingsList
}
}
+ fun removeAccountFromHistory(accountToken: String) {
+ jobTracker.newBackgroundJob("removeAccountFromHistory $accountToken") {
+ daemon.removeAccountFromHistory(accountToken)
+ fetchAccountHistory()
+ }
+ }
+
fun onDestroy() {
settingsListener.accountNumberNotifier.unsubscribe(this)
jobTracker.cancelAllJobs()
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
index 3c55f76b7f..2ba0ba42cb 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
@@ -90,6 +90,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
reconnect(daemonInterfaceAddress)
}
+ fun removeAccountFromHistory(accountToken: String) {
+ removeAccountFromHistory(daemonInterfaceAddress, accountToken)
+ }
+
fun setAccount(accountToken: String?) {
setAccount(daemonInterfaceAddress, accountToken)
}
@@ -147,6 +151,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
private external fun getVersionInfo(daemonInterfaceAddress: Long): AppVersionInfo?
private external fun getWireguardKey(daemonInterfaceAddress: Long): PublicKey?
private external fun reconnect(daemonInterfaceAddress: Long)
+ private external fun removeAccountFromHistory(
+ daemonInterfaceAddress: Long,
+ accountToken: String
+ )
private external fun setAccount(daemonInterfaceAddress: Long, accountToken: String?)
private external fun setAllowLan(daemonInterfaceAddress: Long, allowLan: Boolean)
private external fun setAutoConnect(daemonInterfaceAddress: Long, alwaysOn: Boolean)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
index e19909a0cf..f4b2ea0f7c 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt
@@ -47,8 +47,10 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) {
loggedInStatus = view.findViewById(R.id.logged_in_status)
loginFailStatus = view.findViewById(R.id.login_fail_status)
- accountLogin = view.findViewById(R.id.account_login)
- accountLogin.onLogin = { accountToken -> login(accountToken) }
+ accountLogin = view.findViewById<AccountLogin>(R.id.account_login).apply {
+ onLogin = { accountToken -> login(accountToken) }
+ onRemoveFromHistory = { account -> accountCache.removeAccountFromHistory(account) }
+ }
view.findViewById<Button>(R.id.create_account)
.setOnClickAction("createAccount", jobTracker) { createAccount() }
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryAdapter.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryAdapter.kt
index 155d1d73fc..6e88a2d9a1 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryAdapter.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryAdapter.kt
@@ -19,6 +19,7 @@ class AccountHistoryAdapter : Adapter<AccountHistoryHolder>() {
}
var onSelectEntry: ((String) -> Unit)? = null
+ var onRemoveEntry: ((String) -> Unit)? = null
override fun onCreateViewHolder(parentView: ViewGroup, type: Int): AccountHistoryHolder {
val inflater = LayoutInflater.from(parentView.context)
@@ -26,6 +27,7 @@ class AccountHistoryAdapter : Adapter<AccountHistoryHolder>() {
return AccountHistoryHolder(view, formatter).apply {
onSelect = { account -> onSelectEntry?.invoke(account) }
+ onRemove = { account -> onRemoveEntry?.invoke(account) }
}
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryHolder.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryHolder.kt
index f19da6a5be..e91897af4b 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryHolder.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountHistoryHolder.kt
@@ -18,10 +18,15 @@ class AccountHistoryHolder(
}
var onSelect: ((String) -> Unit)? = null
+ var onRemove: ((String) -> Unit)? = null
init {
view.setOnClickListener {
onSelect?.invoke(accountToken)
}
+
+ view.findViewById<View>(R.id.remove).setOnClickListener {
+ onRemove?.invoke(accountToken)
+ }
}
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt
index 838bd63379..3cc2935c21 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt
@@ -19,6 +19,10 @@ import net.mullvad.mullvadvpn.ui.LoginState
import net.mullvad.mullvadvpn.ui.widget.AccountLoginBorder.BorderState
class AccountLogin : RelativeLayout {
+ companion object {
+ private val MAX_ACCOUNT_HISTORY_ENTRIES = 3
+ }
+
private val container =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE).let { service ->
val inflater = service as LayoutInflater
@@ -46,6 +50,9 @@ class AccountLogin : RelativeLayout {
duration = 350
}
+ private val maxHeight: Int
+ get() = MAX_ACCOUNT_HISTORY_ENTRIES * (historyEntryHeight + dividerHeight)
+
private val expandedHeight: Int
get() = collapsedHeight + historyHeight
@@ -106,6 +113,10 @@ class AccountLogin : RelativeLayout {
get() = input.onLogin
set(value) { input.onLogin = value }
+ var onRemoveFromHistory: ((String) -> Unit)?
+ get() = historyAdapter.onRemoveEntry
+ set(value) { historyAdapter.onRemoveEntry = value }
+
constructor(context: Context) : super(context) {}
constructor(context: Context, attributes: AttributeSet) : super(context, attributes) {}
@@ -173,7 +184,7 @@ class AccountLogin : RelativeLayout {
val layoutParams = container.layoutParams as MarginLayoutParams
layoutParams.height = height
- layoutParams.bottomMargin = expandedHeight - height
+ layoutParams.bottomMargin = maxHeight - height
container.layoutParams = layoutParams
}
diff --git a/android/src/main/res/drawable/account_history_remove.xml b/android/src/main/res/drawable/account_history_remove.xml
new file mode 100644
index 0000000000..6c7f52fcba
--- /dev/null
+++ b/android/src/main/res/drawable/account_history_remove.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <item android:state_pressed="false"
+ android:drawable="@drawable/account_history_remove_normal" />
+ <item android:state_pressed="true"
+ android:drawable="@drawable/account_history_remove_pressed" />
+</selector>
diff --git a/android/src/main/res/drawable/account_history_remove_normal.xml b/android/src/main/res/drawable/account_history_remove_normal.xml
new file mode 100644
index 0000000000..532d6cd9d7
--- /dev/null
+++ b/android/src/main/res/drawable/account_history_remove_normal.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path android:fillColor="#66294D73"
+ android:pathData="
+ M 12,24
+ C 5.37312,24 0,18.62688 0,12
+ C 0,5.37312 5.37312,0 12,0
+ C 18.62688,0 24,5.37312 24,12
+ C 24,18.62688 18.62688,24 12,24
+ Z
+ M 13.5,12
+ L 17.2947612,8.20523878
+ C 17.6857559,7.81424414 17.6838785,7.18387854 17.293923,6.79392296
+ L 17.206077,6.70607704
+ C 16.8181114,6.31811142 16.1842538,6.31574616 15.7947612,6.70523878
+ L 12,10.5
+ L 8.20523878,6.70523878
+ C 7.81574616,6.31574616 7.18188858,6.31811142 6.79392296,6.70607704
+ L 6.70607704,6.79392296
+ C 6.31612146,7.18387854 6.31424414,7.81424414 6.70523878,8.20523878
+ L 10.5,12
+ L 6.70523878,15.7947612
+ C 6.31424414,16.1857559 6.31612146,16.8161215 6.70607704,17.206077
+ L 6.79392296,17.293923
+ C 7.18188858,17.6818886 7.81574616,17.6842538 8.20523878,17.2947612
+ L 12,13.5
+ L 15.7947612,17.2947612
+ C 16.1842538,17.6842538 16.8181114,17.6818886 17.206077,17.293923
+ L 17.293923,17.206077
+ C 17.6838785,16.8161215 17.6857559,16.1857559 17.2947612,15.7947612
+ L 13.5,12
+ L13.5,12
+ Z" />
+</vector>
diff --git a/android/src/main/res/drawable/account_history_remove_pressed.xml b/android/src/main/res/drawable/account_history_remove_pressed.xml
new file mode 100644
index 0000000000..49d3484460
--- /dev/null
+++ b/android/src/main/res/drawable/account_history_remove_pressed.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path android:fillColor="#FF294D73"
+ android:pathData="
+ M 12,24
+ C 5.37312,24 0,18.62688 0,12
+ C 0,5.37312 5.37312,0 12,0
+ C 18.62688,0 24,5.37312 24,12
+ C 24,18.62688 18.62688,24 12,24
+ Z
+ M 13.5,12
+ L 17.2947612,8.20523878
+ C 17.6857559,7.81424414 17.6838785,7.18387854 17.293923,6.79392296
+ L 17.206077,6.70607704
+ C 16.8181114,6.31811142 16.1842538,6.31574616 15.7947612,6.70523878
+ L 12,10.5
+ L 8.20523878,6.70523878
+ C 7.81574616,6.31574616 7.18188858,6.31811142 6.79392296,6.70607704
+ L 6.70607704,6.79392296
+ C 6.31612146,7.18387854 6.31424414,7.81424414 6.70523878,8.20523878
+ L 10.5,12
+ L 6.70523878,15.7947612
+ C 6.31424414,16.1857559 6.31612146,16.8161215 6.70607704,17.206077
+ L 6.79392296,17.293923
+ C 7.18188858,17.6818886 7.81574616,17.6842538 8.20523878,17.2947612
+ L 12,13.5
+ L 15.7947612,17.2947612
+ C 16.1842538,17.6842538 16.8181114,17.6818886 17.206077,17.293923
+ L 17.293923,17.206077
+ C 17.6838785,16.8161215 17.6857559,16.1857559 17.2947612,15.7947612
+ L 13.5,12
+ L13.5,12
+ Z" />
+</vector>
diff --git a/android/src/main/res/layout/account_history_entry.xml b/android/src/main/res/layout/account_history_entry.xml
index d168bc6cc1..d410b5138c 100644
--- a/android/src/main/res/layout/account_history_entry.xml
+++ b/android/src/main/res/layout/account_history_entry.xml
@@ -1,7 +1,6 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="@dimen/account_history_entry_height"
- android:orientation="vertical">
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/account_history_entry_height">
<TextView android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -11,4 +10,10 @@
android:textColor="@color/blue80"
android:textSize="@dimen/text_medium_plus"
android:textStyle="bold" />
-</LinearLayout>
+ <ImageButton android:id="@+id/remove"
+ android:layout_width="@dimen/account_history_entry_height"
+ android:layout_height="@dimen/account_history_entry_height"
+ android:layout_gravity="right"
+ android:background="?android:attr/selectableItemBackground"
+ android:src="@drawable/account_history_remove" />
+</FrameLayout>
diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs
index d8a3b980cf..40d9e9cc35 100644
--- a/mullvad-jni/src/daemon_interface.rs
+++ b/mullvad-jni/src/daemon_interface.rs
@@ -153,6 +153,14 @@ impl DaemonInterface {
Ok(())
}
+ pub fn remove_account_from_history(&self, account_token: String) -> Result<()> {
+ let (tx, rx) = oneshot::channel();
+
+ self.send_command(DaemonCommand::RemoveAccountFromHistory(tx, account_token))?;
+
+ block_on(rx).map_err(|_| Error::NoResponse)
+ }
+
pub fn get_wireguard_key(&self) -> Result<Option<wireguard::PublicKey>> {
let (tx, rx) = oneshot::channel();
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 1abd4d093d..cabd7782bc 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -724,6 +724,28 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_reconne
#[no_mangle]
#[allow(non_snake_case)]
+pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_removeAccountFromHistory(
+ env: JNIEnv<'_>,
+ _: JObject<'_>,
+ daemon_interface_address: jlong,
+ accountToken: JString<'_>,
+) {
+ let env = JnixEnv::from(env);
+
+ if let Some(daemon_interface) = get_daemon_interface(daemon_interface_address) {
+ let account = String::from_java(&env, accountToken);
+
+ if let Err(error) = daemon_interface.remove_account_from_history(account) {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to remove account from history")
+ );
+ }
+ }
+}
+
+#[no_mangle]
+#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_setAccount(
env: JNIEnv<'_>,
_: JObject<'_>,