mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 22:59:54 +01:00
Merge branch 'plugin-toggle-settings' into 'plugin-toggles'
Add toggle settings for transport plugins See merge request briar/briar!1211
This commit is contained in:
@@ -9,11 +9,11 @@ import android.net.wifi.WifiManager;
|
|||||||
|
|
||||||
import org.briarproject.bramble.PoliteExecutor;
|
import org.briarproject.bramble.PoliteExecutor;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
|
||||||
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Backoff;
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
import org.briarproject.bramble.api.plugin.PluginCallback;
|
import org.briarproject.bramble.api.plugin.PluginCallback;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -36,10 +36,11 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
|
class AndroidLanTcpPlugin extends LanTcpPlugin {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(AndroidLanTcpPlugin.class.getName());
|
getLogger(AndroidLanTcpPlugin.class.getName());
|
||||||
@@ -83,7 +84,8 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
state.setStarted();
|
Settings settings = callback.getSettings();
|
||||||
|
state.setStarted(settings.getBoolean(PREF_TCP_ENABLE, false));
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +138,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
|
super.eventOccurred(e);
|
||||||
if (e instanceof NetworkStatusEvent) updateConnectionStatus();
|
if (e instanceof NetworkStatusEvent) updateConnectionStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,7 @@ public interface BluetoothConstants {
|
|||||||
String PROP_UUID = "uuid";
|
String PROP_UUID = "uuid";
|
||||||
|
|
||||||
String PREF_BT_ENABLE = "enable";
|
String PREF_BT_ENABLE = "enable";
|
||||||
|
|
||||||
|
// Reason code returned by Plugin#getReasonDisabled()
|
||||||
|
int REASON_NO_BT_ADAPTER = 2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,18 @@ public interface Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reason code returned by {@link #getReasonDisabled()} ()} to indicate
|
* Reason code returned by {@link #getReasonDisabled()} to indicate that
|
||||||
* that the plugin is disabled because it has not been started or has been
|
* the plugin is disabled because it has not been started or has been
|
||||||
* stopped.
|
* stopped.
|
||||||
*/
|
*/
|
||||||
int REASON_STARTING_STOPPING = 0;
|
int REASON_STARTING_STOPPING = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reason code returned by {@link #getReasonDisabled()} to indicate that
|
||||||
|
* the plugin has been disabled by the user.
|
||||||
|
*/
|
||||||
|
int REASON_USER = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the plugin's transport identifier.
|
* Returns the plugin's transport identifier.
|
||||||
*/
|
*/
|
||||||
@@ -75,9 +81,9 @@ public interface Plugin {
|
|||||||
* Returns an integer code indicating why the plugin is
|
* Returns an integer code indicating why the plugin is
|
||||||
* {@link State#DISABLED disabled}, or -1 if the plugin is not disabled.
|
* {@link State#DISABLED disabled}, or -1 if the plugin is not disabled.
|
||||||
* <p>
|
* <p>
|
||||||
* The codes used are plugin-specific, except the generic code
|
* The codes used are plugin-specific, except the generic codes
|
||||||
* {@link #REASON_STARTING_STOPPING}, which may be used by
|
* {@link #REASON_STARTING_STOPPING} and {@link #REASON_USER}, which may
|
||||||
* any plugin.
|
* be used by any plugin.
|
||||||
*/
|
*/
|
||||||
int getReasonDisabled();
|
int getReasonDisabled();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.briarproject.bramble.api.plugin;
|
||||||
|
|
||||||
|
public interface TcpConstants {
|
||||||
|
|
||||||
|
String PREF_TCP_ENABLE = "enable";
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ public interface TorConstants {
|
|||||||
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
|
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
|
||||||
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
|
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
|
||||||
|
|
||||||
|
String PREF_TOR_ENABLE = "enable";
|
||||||
String PREF_TOR_NETWORK = "network2";
|
String PREF_TOR_NETWORK = "network2";
|
||||||
String PREF_TOR_PORT = "port";
|
String PREF_TOR_PORT = "port";
|
||||||
String PREF_TOR_MOBILE = "useMobileData";
|
String PREF_TOR_MOBILE = "useMobileData";
|
||||||
@@ -23,7 +24,7 @@ public interface TorConstants {
|
|||||||
int PREF_TOR_NETWORK_WITH_BRIDGES = 2;
|
int PREF_TOR_NETWORK_WITH_BRIDGES = 2;
|
||||||
int PREF_TOR_NETWORK_NEVER = 3;
|
int PREF_TOR_NETWORK_NEVER = 3;
|
||||||
|
|
||||||
int REASON_USER = 1;
|
// Reason codes returned by Plugin#getReasonDisabled()
|
||||||
int REASON_BATTERY = 2;
|
int REASON_BATTERY = 2;
|
||||||
int REASON_MOBILE_DATA = 3;
|
int REASON_MOBILE_DATA = 3;
|
||||||
int REASON_COUNTRY_BLOCKED = 4;
|
int REASON_COUNTRY_BLOCKED = 4;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
|||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
|
||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStoppedListeningEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStoppedListeningEvent;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
@@ -48,6 +49,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
|
|||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.REASON_NO_BT_ADAPTER;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
||||||
@@ -76,7 +78,6 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
|
|
||||||
protected final PluginState state = new PluginState();
|
protected final PluginState state = new PluginState();
|
||||||
|
|
||||||
private volatile boolean contactConnections = false;
|
|
||||||
private volatile String contactConnectionsUuid = null;
|
private volatile String contactConnectionsUuid = null;
|
||||||
|
|
||||||
abstract void initialiseAdapter() throws IOException;
|
abstract void initialiseAdapter() throws IOException;
|
||||||
@@ -126,16 +127,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
LOG.info("Bluetooth enabled");
|
LOG.info("Bluetooth enabled");
|
||||||
// We may not have been able to get the local address before
|
// We may not have been able to get the local address before
|
||||||
ioExecutor.execute(this::updateProperties);
|
ioExecutor.execute(this::updateProperties);
|
||||||
if (shouldAllowContactConnections()) bind();
|
if (getState() == INACTIVE) bind();
|
||||||
callback.pluginStateChanged(getState());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAdapterDisabled() {
|
void onAdapterDisabled() {
|
||||||
LOG.info("Bluetooth disabled");
|
LOG.info("Bluetooth disabled");
|
||||||
connectionLimiter.allConnectionsClosed();
|
connectionLimiter.allConnectionsClosed();
|
||||||
// The server socket may not have been closed automatically
|
// The server socket may not have been closed automatically
|
||||||
tryToClose(state.clearServerSocket());
|
SS ss = state.clearServerSocket();
|
||||||
callback.pluginStateChanged(getState());
|
if (ss != null) {
|
||||||
|
LOG.info("Closing server socket");
|
||||||
|
tryToClose(ss);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -160,29 +163,22 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
try {
|
try {
|
||||||
initialiseAdapter();
|
initialiseAdapter();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
state.setNoAdapter();
|
||||||
throw new PluginException(e);
|
throw new PluginException(e);
|
||||||
}
|
}
|
||||||
updateProperties();
|
updateProperties();
|
||||||
state.setStarted();
|
Settings settings = callback.getSettings();
|
||||||
loadSettings(callback.getSettings());
|
boolean enabledByUser = settings.getBoolean(PREF_BT_ENABLE, false);
|
||||||
if (shouldAllowContactConnections()) {
|
state.setStarted(enabledByUser);
|
||||||
|
if (enabledByUser) {
|
||||||
if (isAdapterEnabled()) bind();
|
if (isAdapterEnabled()) bind();
|
||||||
else enableAdapter();
|
else enableAdapter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSettings(Settings settings) {
|
|
||||||
contactConnections = settings.getBoolean(PREF_BT_ENABLE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldAllowContactConnections() {
|
|
||||||
return contactConnections;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
if (!shouldAllowContactConnections() || getState() != ACTIVE)
|
if (getState() != INACTIVE) return;
|
||||||
return;
|
|
||||||
// Bind a server socket to accept connections from contacts
|
// Bind a server socket to accept connections from contacts
|
||||||
SS ss;
|
SS ss;
|
||||||
try {
|
try {
|
||||||
@@ -191,8 +187,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!shouldAllowContactConnections() ||
|
if (!state.setServerSocket(ss)) {
|
||||||
!state.setServerSocket(ss)) {
|
|
||||||
LOG.info("Closing redundant server socket");
|
LOG.info("Closing redundant server socket");
|
||||||
tryToClose(ss);
|
tryToClose(ss);
|
||||||
return;
|
return;
|
||||||
@@ -259,7 +254,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getReasonDisabled() {
|
public int getReasonDisabled() {
|
||||||
return getState() == DISABLED ? REASON_STARTING_STOPPING : -1;
|
return state.getReasonDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -275,7 +270,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
|
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
|
||||||
properties) {
|
properties) {
|
||||||
if (!shouldAllowContactConnections() || getState() != ACTIVE) return;
|
if (getState() != ACTIVE) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
|
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
|
||||||
connect(p.getFirst(), p.getSecond());
|
connect(p.getFirst(), p.getSecond());
|
||||||
@@ -288,8 +283,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
String uuid = p.get(PROP_UUID);
|
String uuid = p.get(PROP_UUID);
|
||||||
if (isNullOrEmpty(uuid)) return;
|
if (isNullOrEmpty(uuid)) return;
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
if (!shouldAllowContactConnections() || getState() != ACTIVE)
|
if (getState() != ACTIVE) return;
|
||||||
return;
|
|
||||||
if (!connectionLimiter.canOpenContactConnection()) return;
|
if (!connectionLimiter.canOpenContactConnection()) return;
|
||||||
DuplexTransportConnection d = createConnection(p);
|
DuplexTransportConnection d = createConnection(p);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
@@ -333,8 +327,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(TransportProperties p) {
|
public DuplexTransportConnection createConnection(TransportProperties p) {
|
||||||
if (!shouldAllowContactConnections() || getState() != ACTIVE)
|
if (getState() != ACTIVE) return null;
|
||||||
return null;
|
|
||||||
if (!connectionLimiter.canOpenContactConnection()) return null;
|
if (!connectionLimiter.canOpenContactConnection()) return null;
|
||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
if (isNullOrEmpty(address)) return null;
|
if (isNullOrEmpty(address)) return null;
|
||||||
@@ -439,16 +432,17 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IoExecutor
|
||||||
private void onSettingsUpdated(Settings settings) {
|
private void onSettingsUpdated(Settings settings) {
|
||||||
boolean wasAllowed = shouldAllowContactConnections();
|
boolean enabledByUser = settings.getBoolean(PREF_BT_ENABLE, false);
|
||||||
loadSettings(settings);
|
SS ss = state.setEnabledByUser(enabledByUser);
|
||||||
boolean isAllowed = shouldAllowContactConnections();
|
State s = getState();
|
||||||
if (wasAllowed && !isAllowed) {
|
if (ss != null) {
|
||||||
LOG.info("Contact connections disabled");
|
LOG.info("Disabled by user, closing server socket");
|
||||||
tryToClose(state.clearServerSocket());
|
tryToClose(ss);
|
||||||
disableAdapterIfEnabledByUs();
|
disableAdapterIfEnabledByUs();
|
||||||
} else if (!wasAllowed && isAllowed) {
|
} else if (s == INACTIVE) {
|
||||||
LOG.info("Contact connections enabled");
|
LOG.info("Enabled by user, opening server socket");
|
||||||
if (isAdapterEnabled()) bind();
|
if (isAdapterEnabled()) bind();
|
||||||
else enableAdapter();
|
else enableAdapter();
|
||||||
}
|
}
|
||||||
@@ -482,13 +476,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
protected class PluginState {
|
protected class PluginState {
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private boolean started = false, stopped = false;
|
private boolean started = false,
|
||||||
|
stopped = false,
|
||||||
|
noAdapter = false,
|
||||||
|
enabledByUser = false;
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
@Nullable
|
@Nullable
|
||||||
private SS serverSocket = null;
|
private SS serverSocket = null;
|
||||||
|
|
||||||
synchronized void setStarted() {
|
synchronized void setStarted(boolean enabledByUser) {
|
||||||
started = true;
|
started = true;
|
||||||
|
this.enabledByUser = enabledByUser;
|
||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +500,23 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized void setNoAdapter() {
|
||||||
|
noAdapter = true;
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
synchronized SS setEnabledByUser(boolean enabledByUser) {
|
||||||
|
this.enabledByUser = enabledByUser;
|
||||||
|
SS ss = null;
|
||||||
|
if (!enabledByUser) {
|
||||||
|
ss = serverSocket;
|
||||||
|
serverSocket = null;
|
||||||
|
}
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized boolean setServerSocket(SS ss) {
|
synchronized boolean setServerSocket(SS ss) {
|
||||||
if (stopped || serverSocket != null) return false;
|
if (stopped || serverSocket != null) return false;
|
||||||
serverSocket = ss;
|
serverSocket = ss;
|
||||||
@@ -512,12 +528,19 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
synchronized SS clearServerSocket() {
|
synchronized SS clearServerSocket() {
|
||||||
SS ss = serverSocket;
|
SS ss = serverSocket;
|
||||||
serverSocket = null;
|
serverSocket = null;
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized State getState() {
|
synchronized State getState() {
|
||||||
if (!started || stopped) return DISABLED;
|
if (!started || stopped || !enabledByUser) return DISABLED;
|
||||||
return isAdapterEnabled() ? ACTIVE : INACTIVE;
|
return serverSocket == null ? INACTIVE : ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized int getReasonDisabled() {
|
||||||
|
if (noAdapter && !stopped) return REASON_NO_BT_ADAPTER;
|
||||||
|
if (!started || stopped) return REASON_STARTING_STOPPING;
|
||||||
|
return enabledByUser ? -1 : REASON_USER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Backoff;
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||||
@@ -25,11 +26,13 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
|
|||||||
private static final double BACKOFF_BASE = 1.2;
|
private static final double BACKOFF_BASE = 1.2;
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
|
private final EventBus eventBus;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
|
|
||||||
public LanTcpPluginFactory(Executor ioExecutor,
|
public LanTcpPluginFactory(Executor ioExecutor, EventBus eventBus,
|
||||||
BackoffFactory backoffFactory) {
|
BackoffFactory backoffFactory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.eventBus = eventBus;
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +50,9 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
|
|||||||
public DuplexPlugin createPlugin(PluginCallback callback) {
|
public DuplexPlugin createPlugin(PluginCallback callback) {
|
||||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
return new LanTcpPlugin(ioExecutor, backoff, callback, MAX_LATENCY,
|
LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
|
||||||
MAX_IDLE_TIME);
|
MAX_LATENCY, MAX_IDLE_TIME);
|
||||||
|
eventBus.addListener(plugin);
|
||||||
|
return plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ package org.briarproject.bramble.plugin.tcp;
|
|||||||
import org.briarproject.bramble.PoliteExecutor;
|
import org.briarproject.bramble.PoliteExecutor;
|
||||||
import org.briarproject.bramble.api.Pair;
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
@@ -15,6 +18,8 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
|
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
|
||||||
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
|
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -46,6 +51,7 @@ import static java.util.logging.Logger.getLogger;
|
|||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||||
@@ -53,7 +59,7 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
abstract class TcpPlugin implements DuplexPlugin {
|
abstract class TcpPlugin implements DuplexPlugin, EventListener {
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(TcpPlugin.class.getName());
|
private static final Logger LOG = getLogger(TcpPlugin.class.getName());
|
||||||
|
|
||||||
@@ -119,7 +125,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
state.setStarted();
|
Settings settings = callback.getSettings();
|
||||||
|
state.setStarted(settings.getBoolean(PREF_TCP_ENABLE, false));
|
||||||
bind();
|
bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +204,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getReasonDisabled() {
|
public int getReasonDisabled() {
|
||||||
return getState() == DISABLED ? REASON_STARTING_STOPPING : -1;
|
return state.getReasonDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -331,18 +338,43 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof SettingsUpdatedEvent) {
|
||||||
|
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
||||||
|
if (s.getNamespace().equals(getId().getString()))
|
||||||
|
ioExecutor.execute(() -> onSettingsUpdated(s.getSettings()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IoExecutor
|
||||||
|
private void onSettingsUpdated(Settings settings) {
|
||||||
|
boolean enabledByUser = settings.getBoolean(PREF_TCP_ENABLE, false);
|
||||||
|
ServerSocket ss = state.setEnabledByUser(enabledByUser);
|
||||||
|
State s = getState();
|
||||||
|
if (ss != null) {
|
||||||
|
LOG.info("Disabled by user, closing server socket");
|
||||||
|
tryToClose(ss, LOG, WARNING);
|
||||||
|
} else if (s == INACTIVE) {
|
||||||
|
LOG.info("Enabled by user, opening server socket");
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
protected class PluginState {
|
protected class PluginState {
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private boolean started = false, stopped = false;
|
private boolean started = false, stopped = false, enabledByUser = false;
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
@Nullable
|
@Nullable
|
||||||
private ServerSocket serverSocket = null;
|
private ServerSocket serverSocket = null;
|
||||||
|
|
||||||
synchronized void setStarted() {
|
synchronized void setStarted(boolean enabledByUser) {
|
||||||
started = true;
|
started = true;
|
||||||
|
this.enabledByUser = enabledByUser;
|
||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +387,18 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
synchronized ServerSocket setEnabledByUser(boolean enabledByUser) {
|
||||||
|
this.enabledByUser = enabledByUser;
|
||||||
|
ServerSocket ss = null;
|
||||||
|
if (!enabledByUser) {
|
||||||
|
ss = serverSocket;
|
||||||
|
serverSocket = null;
|
||||||
|
}
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
synchronized ServerSocket getServerSocket() {
|
synchronized ServerSocket getServerSocket() {
|
||||||
return serverSocket;
|
return serverSocket;
|
||||||
@@ -373,8 +417,13 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized State getState() {
|
synchronized State getState() {
|
||||||
if (!started || stopped) return DISABLED;
|
if (!started || stopped || !enabledByUser) return DISABLED;
|
||||||
return serverSocket == null ? INACTIVE : ACTIVE;
|
return serverSocket == null ? INACTIVE : ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized int getReasonDisabled() {
|
||||||
|
if (!started || stopped) return REASON_STARTING_STOPPING;
|
||||||
|
return enabledByUser ? -1 : REASON_USER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
|
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Backoff;
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
@@ -26,12 +27,14 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
|
|||||||
private static final double BACKOFF_BASE = 1.2;
|
private static final double BACKOFF_BASE = 1.2;
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
|
private final EventBus eventBus;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
private final ShutdownManager shutdownManager;
|
private final ShutdownManager shutdownManager;
|
||||||
|
|
||||||
public WanTcpPluginFactory(Executor ioExecutor,
|
public WanTcpPluginFactory(Executor ioExecutor, EventBus eventBus,
|
||||||
BackoffFactory backoffFactory, ShutdownManager shutdownManager) {
|
BackoffFactory backoffFactory, ShutdownManager shutdownManager) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.eventBus = eventBus;
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
this.shutdownManager = shutdownManager;
|
this.shutdownManager = shutdownManager;
|
||||||
}
|
}
|
||||||
@@ -50,8 +53,10 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
|
|||||||
public DuplexPlugin createPlugin(PluginCallback callback) {
|
public DuplexPlugin createPlugin(PluginCallback callback) {
|
||||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
return new WanTcpPlugin(ioExecutor, backoff,
|
WanTcpPlugin plugin = new WanTcpPlugin(ioExecutor, backoff,
|
||||||
new PortMapperImpl(shutdownManager), callback, MAX_LATENCY,
|
new PortMapperImpl(shutdownManager), callback, MAX_LATENCY,
|
||||||
MAX_IDLE_TIME);
|
MAX_IDLE_TIME);
|
||||||
|
eventBus.addListener(plugin);
|
||||||
|
return plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
|
|||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
|
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
|
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ENABLE;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
||||||
@@ -87,7 +88,6 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_USER;
|
|
||||||
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
|
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
|
||||||
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
@@ -200,7 +200,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Load the settings
|
// Load the settings
|
||||||
settings = callback.getSettings();
|
settings = migrateSettings(callback.getSettings());
|
||||||
// Install or update the assets if necessary
|
// Install or update the assets if necessary
|
||||||
if (!assetsAreUpToDate()) installAssets();
|
if (!assetsAreUpToDate()) installAssets();
|
||||||
if (cookieFile.exists() && !cookieFile.delete())
|
if (cookieFile.exists() && !cookieFile.delete())
|
||||||
@@ -288,6 +288,18 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
bind();
|
bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove after a reasonable migration period (added 2020-01-16)
|
||||||
|
private Settings migrateSettings(Settings settings) {
|
||||||
|
int network = settings.getInt(PREF_TOR_NETWORK,
|
||||||
|
PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
|
if (network == PREF_TOR_NETWORK_NEVER) {
|
||||||
|
settings.putInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
|
settings.putBoolean(PREF_TOR_ENABLE, false);
|
||||||
|
callback.mergeSettings(settings);
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean assetsAreUpToDate() {
|
private boolean assetsAreUpToDate() {
|
||||||
return doneFile.lastModified() > getLastUpdateTime();
|
return doneFile.lastModified() > getLastUpdateTime();
|
||||||
}
|
}
|
||||||
@@ -763,6 +775,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
String country = locationUtils.getCurrentCountry();
|
String country = locationUtils.getCurrentCountry();
|
||||||
boolean blocked =
|
boolean blocked =
|
||||||
circumventionProvider.isTorProbablyBlocked(country);
|
circumventionProvider.isTorProbablyBlocked(country);
|
||||||
|
boolean enabledByUser = settings.getBoolean(PREF_TOR_ENABLE, true);
|
||||||
int network = settings.getInt(PREF_TOR_NETWORK,
|
int network = settings.getInt(PREF_TOR_NETWORK,
|
||||||
PREF_TOR_NETWORK_AUTOMATIC);
|
PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true);
|
boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true);
|
||||||
@@ -785,7 +798,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
if (!online) {
|
if (!online) {
|
||||||
LOG.info("Disabling network, device is offline");
|
LOG.info("Disabling network, device is offline");
|
||||||
} else if (network == PREF_TOR_NETWORK_NEVER) {
|
} else if (!enabledByUser) {
|
||||||
LOG.info("Disabling network, user has disabled Tor");
|
LOG.info("Disabling network, user has disabled Tor");
|
||||||
disabledBySettings = true;
|
disabledBySettings = true;
|
||||||
reasonDisabled = REASON_USER;
|
reasonDisabled = REASON_USER;
|
||||||
@@ -870,11 +883,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't affect getState()
|
||||||
synchronized void setTorStarted() {
|
synchronized void setTorStarted() {
|
||||||
torStarted = true;
|
torStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
|
||||||
synchronized boolean isTorRunning() {
|
synchronized boolean isTorRunning() {
|
||||||
return torStarted && !stopped;
|
return torStarted && !stopped;
|
||||||
}
|
}
|
||||||
@@ -914,12 +927,14 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't affect getState()
|
||||||
synchronized boolean setServerSocket(ServerSocket ss) {
|
synchronized boolean setServerSocket(ServerSocket ss) {
|
||||||
if (stopped || serverSocket != null) return false;
|
if (stopped || serverSocket != null) return false;
|
||||||
serverSocket = ss;
|
serverSocket = ss;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't affect getState()
|
||||||
synchronized void clearServerSocket(ServerSocket ss) {
|
synchronized void clearServerSocket(ServerSocket ss) {
|
||||||
if (serverSocket == ss) serverSocket = null;
|
if (serverSocket == ss) serverSocket = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import static java.util.concurrent.Executors.newCachedThreadPool;
|
|||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -345,10 +346,15 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
|
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
|
||||||
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
|
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
|
||||||
private final TransportProperties local = new TransportProperties();
|
private final TransportProperties local = new TransportProperties();
|
||||||
|
private final Settings settings = new Settings();
|
||||||
|
|
||||||
|
private Callback() {
|
||||||
|
settings.putBoolean(PREF_TCP_ENABLE, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Settings getSettings() {
|
public Settings getSettings() {
|
||||||
return new Settings();
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ public class DesktopPluginModule extends PluginModule {
|
|||||||
backoffFactory);
|
backoffFactory);
|
||||||
DuplexPluginFactory modem = new ModemPluginFactory(ioExecutor,
|
DuplexPluginFactory modem = new ModemPluginFactory(ioExecutor,
|
||||||
reliabilityFactory);
|
reliabilityFactory);
|
||||||
DuplexPluginFactory lan = new LanTcpPluginFactory(ioExecutor,
|
DuplexPluginFactory lan = new LanTcpPluginFactory(ioExecutor, eventBus,
|
||||||
backoffFactory);
|
backoffFactory);
|
||||||
DuplexPluginFactory wan = new WanTcpPluginFactory(ioExecutor,
|
DuplexPluginFactory wan = new WanTcpPluginFactory(ioExecutor, eventBus,
|
||||||
backoffFactory, shutdownManager);
|
backoffFactory, shutdownManager);
|
||||||
Collection<DuplexPluginFactory> duplex =
|
Collection<DuplexPluginFactory> duplex =
|
||||||
asList(bluetooth, modem, lan, wan);
|
asList(bluetooth, modem, lan, wan);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -79,13 +80,13 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void contactExchangeFailed() {
|
private void contactExchangeFailed() {
|
||||||
showErrorFragment(R.string.connection_error_explanation);
|
showErrorFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@Override
|
@Override
|
||||||
public void keyAgreementFailed() {
|
public void keyAgreementFailed() {
|
||||||
showErrorFragment(R.string.connection_error_explanation);
|
showErrorFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -103,7 +104,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
|
|||||||
@UiThread
|
@UiThread
|
||||||
@Override
|
@Override
|
||||||
public void keyAgreementAborted(boolean remoteAborted) {
|
public void keyAgreementAborted(boolean remoteAborted) {
|
||||||
showErrorFragment(R.string.connection_error_explanation);
|
showErrorFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -112,4 +113,10 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
|
|||||||
startContactExchange(result);
|
startContactExchange(result);
|
||||||
return getString(R.string.exchanging_contact_details);
|
return getString(R.string.exchanging_contact_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void showErrorFragment() {
|
||||||
|
String errorMsg = getString(R.string.connection_error_explanation);
|
||||||
|
BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg);
|
||||||
|
showNextFragment(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,23 @@ import android.content.IntentFilter;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin.State;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
|
import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
|
||||||
|
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
@@ -21,6 +34,7 @@ import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeen
|
|||||||
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment.KeyAgreementEventListener;
|
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment.KeyAgreementEventListener;
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -37,13 +51,18 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
|||||||
import static android.Manifest.permission.CAMERA;
|
import static android.Manifest.permission.CAMERA;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||||
import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
|
||||||
|
|
||||||
@@ -51,10 +70,33 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMI
|
|||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public abstract class KeyAgreementActivity extends BriarActivity implements
|
public abstract class KeyAgreementActivity extends BriarActivity implements
|
||||||
BaseFragmentListener, IntroScreenSeenListener,
|
BaseFragmentListener, IntroScreenSeenListener,
|
||||||
KeyAgreementEventListener {
|
KeyAgreementEventListener, EventListener {
|
||||||
|
|
||||||
private enum BluetoothState {
|
private enum BluetoothDecision {
|
||||||
UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED, DISCOVERABLE
|
/**
|
||||||
|
* We haven't asked the user about Bluetooth discoverability.
|
||||||
|
*/
|
||||||
|
UNKNOWN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device doesn't have a Bluetooth adapter.
|
||||||
|
*/
|
||||||
|
NO_ADAPTER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We're waiting for the user to accept or refuse discoverability.
|
||||||
|
*/
|
||||||
|
WAITING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has accepted discoverability.
|
||||||
|
*/
|
||||||
|
ACCEPTED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has refused discoverability.
|
||||||
|
*/
|
||||||
|
REFUSED
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum Permission {
|
private enum Permission {
|
||||||
@@ -62,11 +104,21 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(KeyAgreementActivity.class.getName());
|
getLogger(KeyAgreementActivity.class.getName());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EventBus eventBus;
|
EventBus eventBus;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PluginManager pluginManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@IoExecutor
|
||||||
|
Executor ioExecutor;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SettingsManager settingsManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to true in onPostResume() and false in onPause(). This prevents the
|
* Set to true in onPostResume() and false in onPause(). This prevents the
|
||||||
* QR code fragment from being shown if onRequestPermissionsResult() is
|
* QR code fragment from being shown if onRequestPermissionsResult() is
|
||||||
@@ -74,21 +126,36 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
* https://issuetracker.google.com/issues/37067655.
|
* https://issuetracker.google.com/issues/37067655.
|
||||||
*/
|
*/
|
||||||
private boolean isResumed = false;
|
private boolean isResumed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to true when the continue button is clicked, and false when the QR
|
* Set to true when the continue button is clicked, and false when the QR
|
||||||
* code fragment is shown. This prevents the QR code fragment from being
|
* code fragment is shown. This prevents the QR code fragment from being
|
||||||
* shown automatically before the continue button has been clicked.
|
* shown automatically before the continue button has been clicked.
|
||||||
*/
|
*/
|
||||||
private boolean continueClicked = false;
|
private boolean continueClicked = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records whether the Bluetooth adapter was already enabled before we
|
* Records whether the Bluetooth adapter was already enabled before we
|
||||||
* asked for Bluetooth discoverability, so we know whether to broadcast a
|
* asked for Bluetooth discoverability, so we know whether to broadcast a
|
||||||
* {@link BluetoothEnabledEvent}.
|
* {@link BluetoothEnabledEvent}.
|
||||||
*/
|
*/
|
||||||
private boolean wasAdapterEnabled = false;
|
private boolean wasAdapterEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records whether we've enabled the wifi plugin so we don't enable it more
|
||||||
|
* than once.
|
||||||
|
*/
|
||||||
|
private boolean hasEnabledWifi = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records whether we've enabled the Bluetooth plugin so we don't enable it
|
||||||
|
* more than once.
|
||||||
|
*/
|
||||||
|
private boolean hasEnabledBluetooth = false;
|
||||||
|
|
||||||
private Permission cameraPermission = Permission.UNKNOWN;
|
private Permission cameraPermission = Permission.UNKNOWN;
|
||||||
private Permission locationPermission = Permission.UNKNOWN;
|
private Permission locationPermission = Permission.UNKNOWN;
|
||||||
private BluetoothState bluetoothState = BluetoothState.UNKNOWN;
|
private BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
|
||||||
private BroadcastReceiver bluetoothReceiver = null;
|
private BroadcastReceiver bluetoothReceiver = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,20 +163,17 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
component.inject(this);
|
component.inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
setContentView(R.layout.activity_fragment_container_toolbar);
|
setContentView(R.layout.activity_fragment_container_toolbar);
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
showInitialFragment(IntroFragment.newInstance());
|
showInitialFragment(IntroFragment.newInstance());
|
||||||
}
|
}
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
||||||
filter.addAction(ACTION_STATE_CHANGED);
|
|
||||||
filter.addAction(ACTION_SCAN_MODE_CHANGED);
|
|
||||||
bluetoothReceiver = new BluetoothStateReceiver();
|
bluetoothReceiver = new BluetoothStateReceiver();
|
||||||
registerReceiver(bluetoothReceiver, filter);
|
registerReceiver(bluetoothReceiver, filter);
|
||||||
}
|
}
|
||||||
@@ -122,18 +186,17 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
case android.R.id.home:
|
onBackPressed();
|
||||||
onBackPressed();
|
return true;
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
eventBus.addListener(this);
|
||||||
// Permissions may have been granted manually while we were stopped
|
// Permissions may have been granted manually while we were stopped
|
||||||
cameraPermission = Permission.UNKNOWN;
|
cameraPermission = Permission.UNKNOWN;
|
||||||
locationPermission = Permission.UNKNOWN;
|
locationPermission = Permission.UNKNOWN;
|
||||||
@@ -150,11 +213,22 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
|
|
||||||
private void showQrCodeFragmentIfAllowed() {
|
private void showQrCodeFragmentIfAllowed() {
|
||||||
if (isResumed && continueClicked && areEssentialPermissionsGranted()) {
|
if (isResumed && continueClicked && areEssentialPermissionsGranted()) {
|
||||||
if (bluetoothState == BluetoothState.UNKNOWN ||
|
if (isWifiReady() && isBluetoothReady()) {
|
||||||
bluetoothState == BluetoothState.ENABLED) {
|
LOG.info("Wifi and Bluetooth are ready");
|
||||||
requestBluetoothDiscoverable();
|
|
||||||
} else if (bluetoothState != BluetoothState.WAITING) {
|
|
||||||
showQrCodeFragment();
|
showQrCodeFragment();
|
||||||
|
} else {
|
||||||
|
if (shouldEnableWifi()) {
|
||||||
|
LOG.info("Enabling wifi plugin");
|
||||||
|
hasEnabledWifi = true;
|
||||||
|
enablePlugin(LanTcpConstants.ID, PREF_TCP_ENABLE);
|
||||||
|
}
|
||||||
|
if (bluetoothDecision == BluetoothDecision.UNKNOWN) {
|
||||||
|
requestBluetoothDiscoverable();
|
||||||
|
} else if (shouldEnableBluetooth()) {
|
||||||
|
LOG.info("Enabling Bluetooth plugin");
|
||||||
|
hasEnabledBluetooth = true;
|
||||||
|
enablePlugin(BluetoothConstants.ID, PREF_BT_ENABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,57 +241,116 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
locationPermission == Permission.PERMANENTLY_DENIED);
|
locationPermission == Permission.PERMANENTLY_DENIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isWifiReady() {
|
||||||
|
Plugin p = pluginManager.getPlugin(LanTcpConstants.ID);
|
||||||
|
if (p == null) return true; // Continue without wifi
|
||||||
|
State state = p.getState();
|
||||||
|
// Wait for plugin to become enabled
|
||||||
|
return state == ACTIVE || state == INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBluetoothReady() {
|
||||||
|
if (bluetoothDecision == BluetoothDecision.UNKNOWN ||
|
||||||
|
bluetoothDecision == BluetoothDecision.WAITING) {
|
||||||
|
// Wait for decision
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bluetoothDecision == BluetoothDecision.NO_ADAPTER
|
||||||
|
|| bluetoothDecision == BluetoothDecision.REFUSED) {
|
||||||
|
// Continue without Bluetooth
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
if (bt == null) return true; // Continue without Bluetooth
|
||||||
|
if (bt.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
|
||||||
|
// Wait for adapter to become discoverable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Plugin p = pluginManager.getPlugin(BluetoothConstants.ID);
|
||||||
|
if (p == null) return true; // Continue without Bluetooth
|
||||||
|
// Wait for plugin to become active
|
||||||
|
return p.getState() == ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldEnableWifi() {
|
||||||
|
if (hasEnabledWifi) return false;
|
||||||
|
Plugin p = pluginManager.getPlugin(LanTcpConstants.ID);
|
||||||
|
return p != null && p.getState() == DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enablePlugin(TransportId t, String settingKey) {
|
||||||
|
ioExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(settingKey, true);
|
||||||
|
settingsManager.mergeSettings(s, t.getString());
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestBluetoothDiscoverable() {
|
||||||
|
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
if (bt == null) {
|
||||||
|
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
|
} else {
|
||||||
|
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
||||||
|
if (i.resolveActivity(getPackageManager()) != null) {
|
||||||
|
LOG.info("Asking for Bluetooth discoverability");
|
||||||
|
bluetoothDecision = BluetoothDecision.WAITING;
|
||||||
|
wasAdapterEnabled = bt.isEnabled();
|
||||||
|
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
|
||||||
|
} else {
|
||||||
|
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldEnableBluetooth() {
|
||||||
|
if (bluetoothDecision != BluetoothDecision.ACCEPTED) return false;
|
||||||
|
if (hasEnabledBluetooth) return false;
|
||||||
|
Plugin p = pluginManager.getPlugin(BluetoothConstants.ID);
|
||||||
|
return p != null && p.getState() == DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
isResumed = false;
|
isResumed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
eventBus.removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showNextScreen() {
|
public void showNextScreen() {
|
||||||
continueClicked = true;
|
continueClicked = true;
|
||||||
if (checkPermissions()) showQrCodeFragmentIfAllowed();
|
if (checkPermissions()) showQrCodeFragmentIfAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestBluetoothDiscoverable() {
|
|
||||||
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
if (bt == null) {
|
|
||||||
setBluetoothState(BluetoothState.NO_ADAPTER);
|
|
||||||
} else {
|
|
||||||
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
|
||||||
if (i.resolveActivity(getPackageManager()) != null) {
|
|
||||||
setBluetoothState(BluetoothState.WAITING);
|
|
||||||
wasAdapterEnabled = bt.isEnabled();
|
|
||||||
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
|
|
||||||
} else {
|
|
||||||
setBluetoothState(BluetoothState.NO_ADAPTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBluetoothState(BluetoothState bluetoothState) {
|
|
||||||
LOG.info("Setting Bluetooth state to " + bluetoothState);
|
|
||||||
this.bluetoothState = bluetoothState;
|
|
||||||
if (!wasAdapterEnabled && bluetoothState == BluetoothState.ENABLED) {
|
|
||||||
eventBus.broadcast(new BluetoothEnabledEvent());
|
|
||||||
wasAdapterEnabled = true;
|
|
||||||
}
|
|
||||||
showQrCodeFragmentIfAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int request, int result, Intent data) {
|
public void onActivityResult(int request, int result,
|
||||||
|
@Nullable Intent data) {
|
||||||
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
|
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
|
||||||
if (result == RESULT_CANCELED) {
|
if (result == RESULT_CANCELED) {
|
||||||
setBluetoothState(BluetoothState.REFUSED);
|
LOG.info("Bluetooth discoverability was refused");
|
||||||
|
bluetoothDecision = BluetoothDecision.REFUSED;
|
||||||
} else {
|
} else {
|
||||||
// If Bluetooth is already discoverable, show the QR code -
|
LOG.info("Bluetooth discoverability was accepted");
|
||||||
// otherwise wait for the state or scan mode to change
|
bluetoothDecision = BluetoothDecision.ACCEPTED;
|
||||||
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
if (!wasAdapterEnabled) {
|
||||||
if (bt == null) throw new AssertionError();
|
LOG.info("Bluetooth adapter was enabled by us");
|
||||||
if (bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE)
|
eventBus.broadcast(new BluetoothEnabledEvent());
|
||||||
setBluetoothState(BluetoothState.DISCOVERABLE);
|
wasAdapterEnabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
} else super.onActivityResult(request, result, data);
|
} else super.onActivityResult(request, result, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +360,12 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
continueClicked = false;
|
continueClicked = false;
|
||||||
// If we return to the intro fragment, ask for Bluetooth
|
// If we return to the intro fragment, ask for Bluetooth
|
||||||
// discoverability again before showing the QR code fragment
|
// discoverability again before showing the QR code fragment
|
||||||
bluetoothState = BluetoothState.UNKNOWN;
|
bluetoothDecision = BluetoothDecision.UNKNOWN;
|
||||||
|
// If we return to the intro fragment, we may need to enable wifi and
|
||||||
|
// Bluetooth again
|
||||||
|
hasEnabledWifi = false;
|
||||||
|
hasEnabledBluetooth = false;
|
||||||
|
|
||||||
// FIXME #824
|
// FIXME #824
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
|
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
|
||||||
@@ -239,12 +377,6 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void showErrorFragment(@StringRes int errorResId) {
|
|
||||||
String errorMsg = getString(errorResId);
|
|
||||||
BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg);
|
|
||||||
showNextFragment(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkPermissions() {
|
private boolean checkPermissions() {
|
||||||
if (areEssentialPermissionsGranted()) return true;
|
if (areEssentialPermissionsGranted()) return true;
|
||||||
// If the camera permission has been permanently denied, ask the
|
// If the camera permission has been permanently denied, ask the
|
||||||
@@ -335,24 +467,30 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
permission);
|
permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof TransportStateEvent) {
|
||||||
|
TransportStateEvent t = (TransportStateEvent) e;
|
||||||
|
if (t.getTransportId().equals(BluetoothConstants.ID)) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Bluetooth state changed to " + t.getState());
|
||||||
|
}
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
|
} else if (t.getTransportId().equals(LanTcpConstants.ID)) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Wifi state changed to " + t.getState());
|
||||||
|
}
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
String action = intent.getAction();
|
LOG.info("Bluetooth scan mode changed");
|
||||||
if (ACTION_STATE_CHANGED.equals(action)) {
|
showQrCodeFragmentIfAllowed();
|
||||||
int state = intent.getIntExtra(EXTRA_STATE, 0);
|
|
||||||
if (state == STATE_ON)
|
|
||||||
setBluetoothState(BluetoothState.ENABLED);
|
|
||||||
else setBluetoothState(BluetoothState.UNKNOWN);
|
|
||||||
} else if (ACTION_SCAN_MODE_CHANGED.equals(action)) {
|
|
||||||
int scanMode = intent.getIntExtra(EXTRA_SCAN_MODE, 0);
|
|
||||||
if (scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE)
|
|
||||||
setBluetoothState(BluetoothState.DISCOVERABLE);
|
|
||||||
else if (scanMode == SCAN_MODE_CONNECTABLE)
|
|
||||||
setBluetoothState(BluetoothState.ENABLED);
|
|
||||||
else setBluetoothState(BluetoothState.UNKNOWN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.briarproject.bramble.api.event.EventListener;
|
|||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
@@ -73,6 +74,8 @@ import static androidx.core.view.ViewCompat.LAYOUT_DIRECTION_LTR;
|
|||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ENABLE;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
||||||
@@ -105,16 +108,24 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
implements EventListener, OnPreferenceChangeListener {
|
implements EventListener, OnPreferenceChangeListener {
|
||||||
|
|
||||||
public static final String SETTINGS_NAMESPACE = "android-ui";
|
public static final String SETTINGS_NAMESPACE = "android-ui";
|
||||||
public static final String BT_NAMESPACE = BluetoothConstants.ID.getString();
|
|
||||||
public static final String TOR_NAMESPACE = TorConstants.ID.getString();
|
|
||||||
public static final String LANGUAGE = "pref_key_language";
|
public static final String LANGUAGE = "pref_key_language";
|
||||||
public static final String PREF_SCREEN_LOCK = "pref_key_lock";
|
public static final String PREF_SCREEN_LOCK = "pref_key_lock";
|
||||||
public static final String PREF_SCREEN_LOCK_TIMEOUT =
|
public static final String PREF_SCREEN_LOCK_TIMEOUT =
|
||||||
"pref_key_lock_timeout";
|
"pref_key_lock_timeout";
|
||||||
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
||||||
public static final String TOR_NETWORK = "pref_key_tor_network";
|
|
||||||
public static final String TOR_MOBILE = "pref_key_tor_mobile_data";
|
private static final String BT_NAMESPACE =
|
||||||
public static final String TOR_ONLY_WHEN_CHARGING =
|
BluetoothConstants.ID.getString();
|
||||||
|
private static final String BT_ENABLE = "pref_key_bluetooth";
|
||||||
|
|
||||||
|
private static final String WIFI_NAMESPACE = LanTcpConstants.ID.getString();
|
||||||
|
private static final String WIFI_ENABLE = "pref_key_wifi";
|
||||||
|
|
||||||
|
private static final String TOR_NAMESPACE = TorConstants.ID.getString();
|
||||||
|
private static final String TOR_ENABLE = "pref_key_tor_enable";
|
||||||
|
private static final String TOR_NETWORK = "pref_key_tor_network";
|
||||||
|
private static final String TOR_MOBILE = "pref_key_tor_mobile_data";
|
||||||
|
private static final String TOR_ONLY_WHEN_CHARGING =
|
||||||
"pref_key_tor_only_when_charging";
|
"pref_key_tor_only_when_charging";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
@@ -122,7 +133,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
private SettingsActivity listener;
|
private SettingsActivity listener;
|
||||||
private ListPreference language;
|
private ListPreference language;
|
||||||
private ListPreference enableBluetooth;
|
private SwitchPreference enableBluetooth;
|
||||||
|
private SwitchPreference enableWifi;
|
||||||
|
private SwitchPreference enableTor;
|
||||||
private ListPreference torNetwork;
|
private ListPreference torNetwork;
|
||||||
private SwitchPreference torMobile;
|
private SwitchPreference torMobile;
|
||||||
private SwitchPreference torOnlyWhenCharging;
|
private SwitchPreference torOnlyWhenCharging;
|
||||||
@@ -137,7 +150,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
private Preference notifySound;
|
private Preference notifySound;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
private volatile Settings settings, btSettings, torSettings;
|
private volatile Settings settings, btSettings, wifiSettings, torSettings;
|
||||||
private volatile boolean settingsLoaded = false;
|
private volatile boolean settingsLoaded = false;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -163,28 +176,23 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
addPreferencesFromResource(R.xml.settings);
|
addPreferencesFromResource(R.xml.settings);
|
||||||
|
|
||||||
language = (ListPreference) findPreference(LANGUAGE);
|
language = findPreference(LANGUAGE);
|
||||||
setLanguageEntries();
|
setLanguageEntries();
|
||||||
ListPreference theme =
|
ListPreference theme = findPreference("pref_key_theme");
|
||||||
(ListPreference) findPreference("pref_key_theme");
|
enableBluetooth = findPreference(BT_ENABLE);
|
||||||
enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth");
|
enableWifi = findPreference(WIFI_ENABLE);
|
||||||
torNetwork = (ListPreference) findPreference(TOR_NETWORK);
|
enableTor = findPreference(TOR_ENABLE);
|
||||||
torMobile = (SwitchPreference) findPreference(TOR_MOBILE);
|
torNetwork = findPreference(TOR_NETWORK);
|
||||||
torOnlyWhenCharging =
|
torMobile = findPreference(TOR_MOBILE);
|
||||||
(SwitchPreference) findPreference(TOR_ONLY_WHEN_CHARGING);
|
torOnlyWhenCharging = findPreference(TOR_ONLY_WHEN_CHARGING);
|
||||||
screenLock = (SwitchPreference) findPreference(PREF_SCREEN_LOCK);
|
screenLock = findPreference(PREF_SCREEN_LOCK);
|
||||||
screenLockTimeout =
|
screenLockTimeout = findPreference(PREF_SCREEN_LOCK_TIMEOUT);
|
||||||
(ListPreference) findPreference(PREF_SCREEN_LOCK_TIMEOUT);
|
notifyPrivateMessages =
|
||||||
notifyPrivateMessages = (SwitchPreference) findPreference(
|
findPreference("pref_key_notify_private_messages");
|
||||||
"pref_key_notify_private_messages");
|
notifyGroupMessages = findPreference("pref_key_notify_group_messages");
|
||||||
notifyGroupMessages = (SwitchPreference) findPreference(
|
notifyForumPosts = findPreference("pref_key_notify_forum_posts");
|
||||||
"pref_key_notify_group_messages");
|
notifyBlogPosts = findPreference("pref_key_notify_blog_posts");
|
||||||
notifyForumPosts = (SwitchPreference) findPreference(
|
notifyVibration = findPreference("pref_key_notify_vibration");
|
||||||
"pref_key_notify_forum_posts");
|
|
||||||
notifyBlogPosts = (SwitchPreference) findPreference(
|
|
||||||
"pref_key_notify_blog_posts");
|
|
||||||
notifyVibration = (SwitchPreference) findPreference(
|
|
||||||
"pref_key_notify_vibration");
|
|
||||||
notifySound = findPreference("pref_key_notify_sound");
|
notifySound = findPreference("pref_key_notify_sound");
|
||||||
|
|
||||||
language.setOnPreferenceChangeListener(this);
|
language.setOnPreferenceChangeListener(this);
|
||||||
@@ -194,8 +202,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
UiUtils.setTheme(getActivity(), (String) newValue);
|
UiUtils.setTheme(getActivity(), (String) newValue);
|
||||||
// bring up parent activity, so it can change its theme as well
|
// bring up parent activity, so it can change its theme as well
|
||||||
// upstream bug: https://issuetracker.google.com/issues/38352704
|
// upstream bug: https://issuetracker.google.com/issues/38352704
|
||||||
Intent intent =
|
Intent intent = new Intent(getActivity(), ENTRY_ACTIVITY);
|
||||||
new Intent(getActivity(), ENTRY_ACTIVITY);
|
|
||||||
intent.setFlags(
|
intent.setFlags(
|
||||||
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
|
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@@ -207,6 +214,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
enableBluetooth.setOnPreferenceChangeListener(this);
|
enableBluetooth.setOnPreferenceChangeListener(this);
|
||||||
|
enableWifi.setOnPreferenceChangeListener(this);
|
||||||
|
enableTor.setOnPreferenceChangeListener(this);
|
||||||
torNetwork.setOnPreferenceChangeListener(this);
|
torNetwork.setOnPreferenceChangeListener(this);
|
||||||
torMobile.setOnPreferenceChangeListener(this);
|
torMobile.setOnPreferenceChangeListener(this);
|
||||||
torOnlyWhenCharging.setOnPreferenceChangeListener(this);
|
torOnlyWhenCharging.setOnPreferenceChangeListener(this);
|
||||||
@@ -335,7 +344,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
boolean blocked =
|
boolean blocked =
|
||||||
circumventionProvider.isTorProbablyBlocked(country);
|
circumventionProvider.isTorProbablyBlocked(country);
|
||||||
boolean useBridges = circumventionProvider.doBridgesWork(country);
|
boolean useBridges = circumventionProvider.doBridgesWork(country);
|
||||||
String setting = getString(R.string.tor_network_setting_without_bridges);
|
String setting =
|
||||||
|
getString(R.string.tor_network_setting_without_bridges);
|
||||||
if (blocked && useBridges) {
|
if (blocked && useBridges) {
|
||||||
setting = getString(R.string.tor_network_setting_with_bridges);
|
setting = getString(R.string.tor_network_setting_with_bridges);
|
||||||
} else if (blocked) {
|
} else if (blocked) {
|
||||||
@@ -352,6 +362,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
long start = now();
|
long start = now();
|
||||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||||
btSettings = settingsManager.getSettings(BT_NAMESPACE);
|
btSettings = settingsManager.getSettings(BT_NAMESPACE);
|
||||||
|
wifiSettings = settingsManager.getSettings(WIFI_NAMESPACE);
|
||||||
torSettings = settingsManager.getSettings(TOR_NAMESPACE);
|
torSettings = settingsManager.getSettings(TOR_NAMESPACE);
|
||||||
settingsLoaded = true;
|
settingsLoaded = true;
|
||||||
logDuration(LOG, "Loading settings", start);
|
logDuration(LOG, "Loading settings", start);
|
||||||
@@ -369,7 +380,15 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
boolean btEnabledSetting =
|
boolean btEnabledSetting =
|
||||||
btSettings.getBoolean(PREF_BT_ENABLE, false);
|
btSettings.getBoolean(PREF_BT_ENABLE, false);
|
||||||
enableBluetooth.setValue(Boolean.toString(btEnabledSetting));
|
enableBluetooth.setChecked(btEnabledSetting);
|
||||||
|
|
||||||
|
boolean wifiEnabledSetting =
|
||||||
|
wifiSettings.getBoolean(PREF_TCP_ENABLE, false);
|
||||||
|
enableWifi.setChecked(wifiEnabledSetting);
|
||||||
|
|
||||||
|
boolean torEnabledSetting =
|
||||||
|
torSettings.getBoolean(PREF_TOR_ENABLE, true);
|
||||||
|
enableTor.setChecked(torEnabledSetting);
|
||||||
|
|
||||||
int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
||||||
PREF_TOR_NETWORK_AUTOMATIC);
|
PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
@@ -443,6 +462,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
// - pref_key_lock (screenLock -> displayScreenLockSetting())
|
// - pref_key_lock (screenLock -> displayScreenLockSetting())
|
||||||
// - pref_key_lock_timeout (screenLockTimeout)
|
// - pref_key_lock_timeout (screenLockTimeout)
|
||||||
enableBluetooth.setEnabled(enabled);
|
enableBluetooth.setEnabled(enabled);
|
||||||
|
enableWifi.setEnabled(enabled);
|
||||||
|
enableTor.setEnabled(enabled);
|
||||||
torNetwork.setEnabled(enabled);
|
torNetwork.setEnabled(enabled);
|
||||||
torMobile.setEnabled(enabled);
|
torMobile.setEnabled(enabled);
|
||||||
torOnlyWhenCharging.setEnabled(enabled);
|
torOnlyWhenCharging.setEnabled(enabled);
|
||||||
@@ -545,8 +566,14 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
languageChanged((String) newValue);
|
languageChanged((String) newValue);
|
||||||
return false;
|
return false;
|
||||||
} else if (preference == enableBluetooth) {
|
} else if (preference == enableBluetooth) {
|
||||||
boolean btSetting = Boolean.valueOf((String) newValue);
|
boolean btSetting = (Boolean) newValue;
|
||||||
storeBluetoothSettings(btSetting);
|
storeBluetoothSetting(btSetting);
|
||||||
|
} else if (preference == enableWifi) {
|
||||||
|
boolean wifiSetting = (Boolean) newValue;
|
||||||
|
storeWifiSetting(wifiSetting);
|
||||||
|
} else if (preference == enableTor) {
|
||||||
|
boolean torEnabledSetting = (Boolean) newValue;
|
||||||
|
storeTorEnabledSetting(torEnabledSetting);
|
||||||
} else if (preference == torNetwork) {
|
} else if (preference == torNetwork) {
|
||||||
int torNetworkSetting = Integer.valueOf((String) newValue);
|
int torNetworkSetting = Integer.valueOf((String) newValue);
|
||||||
storeTorNetworkSetting(torNetworkSetting);
|
storeTorNetworkSetting(torNetworkSetting);
|
||||||
@@ -610,6 +637,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
builder.show();
|
builder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeTorEnabledSetting(boolean torEnabledSetting) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_TOR_ENABLE, torEnabledSetting);
|
||||||
|
mergeSettings(s, TOR_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
private void storeTorNetworkSetting(int torNetworkSetting) {
|
private void storeTorNetworkSetting(int torNetworkSetting) {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
s.putInt(PREF_TOR_NETWORK, torNetworkSetting);
|
s.putInt(PREF_TOR_NETWORK, torNetworkSetting);
|
||||||
@@ -628,12 +661,18 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
mergeSettings(s, TOR_NAMESPACE);
|
mergeSettings(s, TOR_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeBluetoothSettings(boolean btSetting) {
|
private void storeBluetoothSetting(boolean btSetting) {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
s.putBoolean(PREF_BT_ENABLE, btSetting);
|
s.putBoolean(PREF_BT_ENABLE, btSetting);
|
||||||
mergeSettings(s, BT_NAMESPACE);
|
mergeSettings(s, BT_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeWifiSetting(boolean wifiSetting) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_TCP_ENABLE, wifiSetting);
|
||||||
|
mergeSettings(s, WIFI_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
private void storeSettings(Settings s) {
|
private void storeSettings(Settings s) {
|
||||||
mergeSettings(s, SETTINGS_NAMESPACE);
|
mergeSettings(s, SETTINGS_NAMESPACE);
|
||||||
}
|
}
|
||||||
@@ -696,6 +735,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
LOG.info("Bluetooth settings updated");
|
LOG.info("Bluetooth settings updated");
|
||||||
btSettings = s.getSettings();
|
btSettings = s.getSettings();
|
||||||
displaySettings();
|
displaySettings();
|
||||||
|
} else if (namespace.equals(WIFI_NAMESPACE)) {
|
||||||
|
LOG.info("Wifi settings updated");
|
||||||
|
wifiSettings = s.getSettings();
|
||||||
|
displaySettings();
|
||||||
} else if (namespace.equals(TOR_NAMESPACE)) {
|
} else if (namespace.equals(TOR_NAMESPACE)) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
torSettings = s.getSettings();
|
torSettings = s.getSettings();
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string-array name="boolean_array">
|
|
||||||
<item>true</item>
|
|
||||||
<item>false</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="bt_setting_names">
|
|
||||||
<item>@string/bluetooth_setting_enabled</item>
|
|
||||||
<item>@string/bluetooth_setting_disabled</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="tor_network_setting_names">
|
<string-array name="tor_network_setting_names">
|
||||||
<item>@string/tor_network_setting_automatic</item>
|
<item>@string/tor_network_setting_automatic</item>
|
||||||
<item>@string/tor_network_setting_without_bridges</item>
|
<item>@string/tor_network_setting_without_bridges</item>
|
||||||
@@ -66,6 +57,7 @@
|
|||||||
<item>zh-CN</item>
|
<item>zh-CN</item>
|
||||||
<item>zh-TW</item>
|
<item>zh-TW</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="pref_theme_entries">
|
<string-array name="pref_theme_entries">
|
||||||
<item>@string/pref_theme_light</item>
|
<item>@string/pref_theme_light</item>
|
||||||
<item>@string/pref_theme_dark</item>
|
<item>@string/pref_theme_dark</item>
|
||||||
|
|||||||
@@ -441,12 +441,12 @@
|
|||||||
<string name="pref_theme_auto">Automatic (Daytime)</string>
|
<string name="pref_theme_auto">Automatic (Daytime)</string>
|
||||||
<string name="pref_theme_system">System Default</string>
|
<string name="pref_theme_system">System Default</string>
|
||||||
|
|
||||||
<!-- Settings Network -->
|
<!-- Settings Connections -->
|
||||||
<string name="network_settings_title">Networks</string>
|
<string name="network_settings_title">Connections</string>
|
||||||
<string name="bluetooth_setting">Connect via Bluetooth</string>
|
<string name="bluetooth_setting">Connect to contacts via Bluetooth</string>
|
||||||
<string name="bluetooth_setting_enabled">Whenever contacts are nearby</string>
|
<string name="wifi_setting">Connect to contacts on the same Wi-Fi network</string>
|
||||||
<string name="bluetooth_setting_disabled">Only when adding contacts</string>
|
<string name="tor_enable_title">Connect to contacts via Internet (Tor)</string>
|
||||||
<string name="tor_network_setting">Connect via Internet (Tor)</string>
|
<string name="tor_network_setting">Connection method for Internet (Tor)</string>
|
||||||
<string name="tor_network_setting_automatic">Automatic based on location</string>
|
<string name="tor_network_setting_automatic">Automatic based on location</string>
|
||||||
<string name="tor_network_setting_without_bridges">Use Tor without bridges</string>
|
<string name="tor_network_setting_without_bridges">Use Tor without bridges</string>
|
||||||
<string name="tor_network_setting_with_bridges">Use Tor with bridges</string>
|
<string name="tor_network_setting_with_bridges">Use Tor with bridges</string>
|
||||||
|
|||||||
@@ -29,18 +29,33 @@
|
|||||||
android:layout="@layout/preferences_category"
|
android:layout="@layout/preferences_category"
|
||||||
android:title="@string/network_settings_title">
|
android:title="@string/network_settings_title">
|
||||||
|
|
||||||
<ListPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:entries="@array/bt_setting_names"
|
|
||||||
android:entryValues="@array/boolean_array"
|
|
||||||
android:key="pref_key_bluetooth"
|
android:key="pref_key_bluetooth"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:summary="%s"
|
|
||||||
android:title="@string/bluetooth_setting"
|
android:title="@string/bluetooth_setting"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_key_wifi"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/wifi_setting"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="pref_key_tor_enable"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/tor_enable_title"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
app:iconSpaceReserved="false"/>
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="0"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:entries="@array/tor_network_setting_names"
|
android:entries="@array/tor_network_setting_names"
|
||||||
android:entryValues="@array/tor_network_setting_values"
|
android:entryValues="@array/tor_network_setting_values"
|
||||||
android:key="pref_key_tor_network"
|
android:key="pref_key_tor_network"
|
||||||
@@ -51,6 +66,7 @@
|
|||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:key="pref_key_tor_mobile_data"
|
android:key="pref_key_tor_mobile_data"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/tor_mobile_data_title"
|
android:title="@string/tor_mobile_data_title"
|
||||||
@@ -59,6 +75,7 @@
|
|||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:key="pref_key_tor_only_when_charging"
|
android:key="pref_key_tor_only_when_charging"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/tor_only_when_charging_title"
|
android:title="@string/tor_only_when_charging_title"
|
||||||
|
|||||||
Reference in New Issue
Block a user