@@ -5,8 +5,9 @@ | |||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
package="com.wireguard.android.tunnel"> | |||
<application> | |||
<service | |||
<service | |||
android:name="com.wireguard.android.backend.GoBackend$VpnService" | |||
android:permission="android.permission.BIND_VPN_SERVICE"> | |||
<intent-filter> | |||
@@ -11,6 +11,7 @@ import com.wireguard.util.NonNullForAll; | |||
public final class BackendException extends Exception { | |||
private final Object[] format; | |||
private final Reason reason; | |||
public BackendException(final Reason reason, final Object... format) { | |||
this.reason = reason; | |||
this.format = format; | |||
@@ -42,6 +42,7 @@ public final class GoBackend implements Backend { | |||
@Nullable private Config currentConfig; | |||
@Nullable private Tunnel currentTunnel; | |||
private int currentTunnelHandle = -1; | |||
public GoBackend(final Context context) { | |||
SharedLibraryLoader.loadSharedLibrary(context, "wg-go"); | |||
this.context = context; | |||
@@ -189,6 +189,7 @@ public class RootShell { | |||
public static class RootShellException extends Exception { | |||
private final Object[] format; | |||
private final Reason reason; | |||
public RootShellException(final Reason reason, final Object... format) { | |||
this.reason = reason; | |||
this.format = format; | |||
@@ -18,9 +18,11 @@ import java.io.InputStream; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import static org.junit.Assert.*; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.fail; | |||
public class BadConfigExceptionTest { | |||
private static final Map<String, InputStream> CONFIG_MAP = new HashMap<>(); | |||
private static final String[] CONFIG_NAMES = { | |||
"invalid-key", | |||
"invalid-number", | |||
@@ -31,14 +33,6 @@ public class BadConfigExceptionTest { | |||
"unknown-attribute", | |||
"unknown-section" | |||
}; | |||
private static final Map<String, InputStream> CONFIG_MAP = new HashMap<>(); | |||
@BeforeClass | |||
public static void readConfigs() { | |||
for (final String config: CONFIG_NAMES) { | |||
CONFIG_MAP.put(config, BadConfigExceptionTest.class.getClassLoader().getResourceAsStream(config + ".conf")); | |||
} | |||
} | |||
@AfterClass | |||
public static void closeStreams() { | |||
@@ -50,6 +44,13 @@ public class BadConfigExceptionTest { | |||
} | |||
} | |||
@BeforeClass | |||
public static void readConfigs() { | |||
for (final String config : CONFIG_NAMES) { | |||
CONFIG_MAP.put(config, BadConfigExceptionTest.class.getClassLoader().getResourceAsStream(config + ".conf")); | |||
} | |||
} | |||
@Test | |||
public void throws_correctly_with_INVALID_KEY_reason() { | |||
try { | |||
@@ -5,7 +5,6 @@ | |||
package com.wireguard.config; | |||
import static org.junit.Assert.*; | |||
import org.junit.Test; | |||
import java.io.IOException; | |||
@@ -15,8 +14,20 @@ import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.Objects; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assert.fail; | |||
public class ConfigTest { | |||
@Test(expected = BadConfigException.class) | |||
public void invalid_config_throws() throws IOException, BadConfigException { | |||
try (final InputStream is = Objects.requireNonNull(getClass().getClassLoader()).getResourceAsStream("broken.conf")) { | |||
Config.parse(is); | |||
} | |||
} | |||
@Test | |||
public void valid_config_parses_correctly() throws IOException, ParseException { | |||
Config config = null; | |||
@@ -35,11 +46,4 @@ public class ConfigTest { | |||
assertEquals("Test config's allowed IPs are 0.0.0.0/0 and ::0/0", config.getPeers().get(0).getAllowedIps(), expectedAllowedIps); | |||
assertEquals("Test config has one DNS server", 1, config.getInterface().getDnsServers().size()); | |||
} | |||
@Test(expected = BadConfigException.class) | |||
public void invalid_config_throws() throws IOException, BadConfigException { | |||
try (final InputStream is = Objects.requireNonNull(getClass().getClassLoader()).getResourceAsStream("broken.conf")) { | |||
Config.parse(is); | |||
} | |||
} | |||
} |
@@ -4,7 +4,6 @@ | |||
*/ | |||
package com.wireguard.android.databinding | |||
import android.annotation.SuppressLint | |||
import android.content.Context | |||
import android.view.LayoutInflater | |||
import android.view.ViewGroup | |||
@@ -7,7 +7,6 @@ package com.wireguard.android.databinding | |||
import java.util.AbstractList | |||
import java.util.Collections | |||
import java.util.Comparator | |||
import java.util.NoSuchElementException | |||
import java.util.Spliterator | |||
/** | |||
@@ -15,9 +15,9 @@ import androidx.fragment.app.Fragment | |||
import com.wireguard.android.Application | |||
import com.wireguard.android.R | |||
import com.wireguard.android.databinding.AppListDialogFragmentBinding | |||
import com.wireguard.android.databinding.ObservableKeyedArrayList | |||
import com.wireguard.android.model.ApplicationData | |||
import com.wireguard.android.util.ErrorMessages | |||
import com.wireguard.android.databinding.ObservableKeyedArrayList | |||
class AppListDialogFragment : DialogFragment() { | |||
private val appData: ObservableKeyedArrayList<String, ApplicationData> = ObservableKeyedArrayList() | |||
@@ -4,7 +4,6 @@ | |||
*/ | |||
package com.wireguard.android.fragment | |||
import android.app.Activity | |||
import android.content.Context | |||
import android.os.Bundle | |||
import android.text.InputType | |||
@@ -9,9 +9,9 @@ import androidx.databinding.Bindable | |||
import com.wireguard.android.BR | |||
import com.wireguard.android.backend.Statistics | |||
import com.wireguard.android.backend.Tunnel | |||
import com.wireguard.android.databinding.Keyed | |||
import com.wireguard.android.util.ExceptionLoggers | |||
import com.wireguard.config.Config | |||
import com.wireguard.android.databinding.Keyed | |||
import java9.util.concurrent.CompletableFuture | |||
import java9.util.concurrent.CompletionStage | |||
@@ -25,7 +25,9 @@ object TunnelComparator : Comparator<String> { | |||
return 0 | |||
} | |||
} | |||
val tokens: MutableList<NaturalSortToken> = ArrayList() | |||
init { | |||
for (s in NATURAL_SORT_DIGIT_FINDER.findAll(originalString.split(WHITESPACE_FINDER).joinToString(" ").toLowerCase(Locale.ENGLISH))) { | |||
try { | |||
@@ -36,6 +38,7 @@ object TunnelComparator : Comparator<String> { | |||
} | |||
} | |||
} | |||
private companion object { | |||
private val NATURAL_SORT_DIGIT_FINDER = Regex("""\d+|\D+""") | |||
private val WHITESPACE_FINDER = Regex("""\s""") | |||
@@ -21,8 +21,8 @@ import com.wireguard.android.R | |||
import com.wireguard.android.backend.Statistics | |||
import com.wireguard.android.backend.Tunnel | |||
import com.wireguard.android.configStore.ConfigStore | |||
import com.wireguard.android.util.ExceptionLoggers | |||
import com.wireguard.android.databinding.ObservableSortedKeyedArrayList | |||
import com.wireguard.android.util.ExceptionLoggers | |||
import com.wireguard.config.Config | |||
import java9.util.concurrent.CompletableFuture | |||
import java9.util.concurrent.CompletionStage | |||
@@ -97,9 +97,9 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference | |||
} | |||
is BiometricAuthenticator.Result.Failure -> { | |||
Snackbar.make( | |||
prefActivity.findViewById(android.R.id.content), | |||
it.message, | |||
Snackbar.LENGTH_SHORT | |||
prefActivity.findViewById(android.R.id.content), | |||
it.message, | |||
Snackbar.LENGTH_SHORT | |||
).show() | |||
} | |||
} | |||
@@ -5,9 +5,9 @@ | |||
package com.wireguard.android.util | |||
import android.os.Handler | |||
import java.util.concurrent.Executor | |||
import java9.util.concurrent.CompletableFuture | |||
import java9.util.concurrent.CompletionStage | |||
import java.util.concurrent.Executor | |||
/** | |||
* Helper class for running asynchronous tasks and ensuring they are completed on the main thread. | |||
@@ -25,25 +25,25 @@ | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:orientation="vertical" | |||
android:background="?attr/colorBackground" | |||
android:clickable="true" | |||
android:focusable="true" | |||
android:background="?attr/colorBackground"> | |||
android:orientation="vertical"> | |||
<com.google.android.material.card.MaterialCardView | |||
android:id="@+id/tunnel_detail_card" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="16dp" | |||
android:layout_marginStart="8dp" | |||
android:layout_marginTop="16dp" | |||
android:layout_marginEnd="8dp" | |||
android:layout_marginBottom="8dp" | |||
app:cardBackgroundColor="?attr/elevationOverlayColor" | |||
app:cardCornerRadius="0dp" | |||
app:cardElevation="2dp" | |||
app:contentPadding="8dp" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent"> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent"> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
@@ -55,8 +55,8 @@ | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="@string/interface_title" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent"/> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<com.wireguard.android.widget.ToggleSwitch | |||
android:id="@+id/tunnel_switch" | |||
@@ -64,9 +64,9 @@ | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="16dp" | |||
app:checked="@{tunnel.state == State.UP}" | |||
app:onBeforeCheckedChanged="@{fragment::setTunnelState}" | |||
app:layout_constraintBaseline_toBaselineOf="@+id/interface_title" | |||
app:layout_constraintEnd_toEndOf="parent"/> | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:onBeforeCheckedChanged="@{fragment::setTunnelState}" /> | |||
<TextView | |||
android:id="@+id/interface_name_label" | |||
@@ -76,7 +76,7 @@ | |||
android:labelFor="@+id/interface_name_text" | |||
android:text="@string/name" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/interface_title"/> | |||
app:layout_constraintTop_toBottomOf="@+id/interface_title" /> | |||
<TextView | |||
android:id="@+id/interface_name_text" | |||
@@ -86,7 +86,7 @@ | |||
android:text="@{tunnel.name}" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/interface_name_label" | |||
tools:text="wg0"/> | |||
tools:text="wg0" /> | |||
<TextView | |||
android:id="@+id/public_key_label" | |||
@@ -96,7 +96,7 @@ | |||
android:labelFor="@+id/public_key_text" | |||
android:text="@string/public_key" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/interface_name_text"/> | |||
app:layout_constraintTop_toBottomOf="@id/interface_name_text" /> | |||
<TextView | |||
android:id="@+id/public_key_text" | |||
@@ -105,13 +105,13 @@ | |||
android:layout_height="wrap_content" | |||
android:contentDescription="@string/public_key_description" | |||
android:ellipsize="end" | |||
android:singleLine="true" | |||
android:maxLines="1" | |||
android:onClick="@{ClipboardUtils::copyTextView}" | |||
android:singleLine="true" | |||
android:text="@{config.interface.keyPair.publicKey.toBase64}" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/public_key_label" | |||
tools:text="wOs2eguFEohqIZxlSJ1CAT9584tc6ejj9hfGFsoBVkA="/> | |||
tools:text="wOs2eguFEohqIZxlSJ1CAT9584tc6ejj9hfGFsoBVkA=" /> | |||
<TextView | |||
android:id="@+id/addresses_label" | |||
@@ -121,7 +121,7 @@ | |||
android:labelFor="@+id/addresses_text" | |||
android:text="@string/addresses" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/public_key_text"/> | |||
app:layout_constraintTop_toBottomOf="@id/public_key_text" /> | |||
<TextView | |||
android:id="@+id/addresses_text" | |||
@@ -132,7 +132,7 @@ | |||
android:text="@{config.interface.addresses}" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/addresses_label" | |||
tools:text="fc00:bbbb:bbbb:bb11::3:368b/128"/> | |||
tools:text="fc00:bbbb:bbbb:bb11::3:368b/128" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</com.google.android.material.card.MaterialCardView> | |||
@@ -145,8 +145,8 @@ | |||
android:orientation="vertical" | |||
app:items="@{config.peers}" | |||
app:layout="@{@layout/tunnel_detail_peer}" | |||
app:layout_constraintTop_toBottomOf="@+id/tunnel_detail_card" | |||
app:layout_constraintStart_toStartOf="parent" | |||
tools:ignore="UselessLeaf"/> | |||
app:layout_constraintTop_toBottomOf="@+id/tunnel_detail_card" | |||
tools:ignore="UselessLeaf" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -31,8 +31,8 @@ | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:text="@string/peer" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent"/> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<TextView | |||
android:id="@+id/public_key_label" | |||
@@ -42,7 +42,7 @@ | |||
android:labelFor="@+id/public_key_text" | |||
android:text="@string/public_key" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/peer_title"/> | |||
app:layout_constraintTop_toBottomOf="@id/peer_title" /> | |||
<TextView | |||
android:id="@+id/public_key_text" | |||
@@ -51,13 +51,13 @@ | |||
android:layout_height="wrap_content" | |||
android:contentDescription="@string/public_key_description" | |||
android:ellipsize="end" | |||
android:singleLine="true" | |||
android:maxLines="1" | |||
android:onClick="@{ClipboardUtils::copyTextView}" | |||
android:singleLine="true" | |||
android:text="@{item.publicKey.toBase64}" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/public_key_label" | |||
tools:text="wOs2eguFEohqIZxlSJ1CAT9584tc6ejj9hfGFsoBVkA="/> | |||
tools:text="wOs2eguFEohqIZxlSJ1CAT9584tc6ejj9hfGFsoBVkA=" /> | |||
<TextView | |||
android:id="@+id/allowed_ips_label" | |||
@@ -67,7 +67,7 @@ | |||
android:labelFor="@+id/allowed_ips_text" | |||
android:text="@string/allowed_ips" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/public_key_text"/> | |||
app:layout_constraintTop_toBottomOf="@+id/public_key_text" /> | |||
<TextView | |||
android:id="@+id/allowed_ips_text" | |||
@@ -77,7 +77,7 @@ | |||
android:text="@{item.allowedIps}" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/allowed_ips_label" | |||
tools:text="0.0.0.0/5, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3"/> | |||
tools:text="0.0.0.0/5, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3" /> | |||
<TextView | |||
android:id="@+id/endpoint_label" | |||
@@ -87,7 +87,7 @@ | |||
android:labelFor="@+id/endpoint_text" | |||
android:text="@string/endpoint" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/allowed_ips_text"/> | |||
app:layout_constraintTop_toBottomOf="@+id/allowed_ips_text" /> | |||
<TextView | |||
android:id="@+id/endpoint_text" | |||
@@ -121,8 +121,8 @@ | |||
android:visibility="gone" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/transfer_label" | |||
tools:visibility="visible" | |||
tools:text="1024 MB" /> | |||
tools:text="1024 MB" | |||
tools:visibility="visible" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</com.google.android.material.card.MaterialCardView> | |||
</layout> |
@@ -55,6 +55,7 @@ | |||
</style> | |||
<style name="DetailText" parent="TextAppearance.MaterialComponents.Body1" /> | |||
<style name="SectionText" parent="TextAppearance.MaterialComponents.Subtitle1" /> | |||
<style name="ThemeOverlay.AppTheme.TextInputEditText.OutlinedBox" parent="ThemeOverlay.MaterialComponents.TextInputEditText.OutlinedBox"> | |||
@@ -64,6 +65,8 @@ | |||
<style name="TextInputLayoutBase" parent="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"> | |||
<item name="boxStrokeColor">?attr/colorSecondary</item> | |||
<item name="hintTextColor">?attr/colorOnPrimary</item> | |||
<item name="materialThemeOverlay">@style/ThemeOverlay.AppTheme.TextInputEditText.OutlinedBox</item> | |||
<item name="materialThemeOverlay"> | |||
@style/ThemeOverlay.AppTheme.TextInputEditText.OutlinedBox | |||
</item> | |||
</style> | |||
</resources> |