Compare commits

...

27 Commits

Author SHA1 Message Date
Torsten Grote
1a9fe070b0 DO NOT MERGE: Return fake image attachements in MessagingManager 2019-03-06 09:51:33 -03:00
akwizgran
144ea0c2fc Merge branch '875-sharing-status-screen-updates' into 'master'
Update memberlists while they are open

Closes #875

See merge request briar/briar!1048
2019-02-28 13:27:19 +00:00
Torsten Grote
a917ebdc76 [android] Close memberlist or sharing status screen when group was left 2019-02-28 09:25:18 -03:00
Torsten Grote
2a389c74dc [android] when sharing a forum or blog, add peers to list while it is open 2019-02-28 09:25:08 -03:00
Torsten Grote
ef16d096f1 [android] add group members to memberlist when they join 2019-02-28 09:25:08 -03:00
akwizgran
679455888b Merge branch '833-ui-reference' into 'master'
Don't pass UI classes to the core, use events instead

See merge request briar/briar!1044
2019-02-28 11:11:14 +00:00
akwizgran
d4372ddae7 Merge branch 'headless-document-build' into 'master'
Briar Headless: Document build process

See merge request briar/briar!1042
2019-02-28 11:10:24 +00:00
Nico Alt
c3ef990a94 Briar Headless: Document build process 2019-02-27 21:27:04 +01:00
Torsten Grote
9422ba2718 Don't pass UI classes to the core, use events instead
This removed the ContactExchangeListener in favor of new events
2019-02-27 13:55:33 -03:00
akwizgran
8343f5c2db Merge branch 'objective-c' into 'master'
Remove Objective C from code styles

See merge request briar/briar!1051
2019-02-27 13:42:08 +00:00
akwizgran
371c7efb04 Merge branch '1106-memberlist-button' into 'master'
Move group memberlist button to overflow menu

See merge request briar/briar!1052
2019-02-27 13:40:19 +00:00
Torsten Grote
92d67645ab [android] move group memberlist button to overflow menu 2019-02-27 10:25:41 -03:00
Torsten Grote
a20e868970 Remove Objective C from code styles 2019-02-27 10:14:22 -03:00
akwizgran
dd853f6718 Merge branch '1475-status-bar-return-transition' into 'master'
Show the status bar when finishing ImageActivity

See merge request briar/briar!1036
2019-02-27 13:11:29 +00:00
akwizgran
16a8ad996a Merge branch '869-remove-group-button' into 'master'
[android] Fix private group status text over remove button

Closes #869

See merge request briar/briar!1047
2019-02-27 11:36:06 +00:00
akwizgran
e27885f0c8 Merge branch '850-initial-group-sharing-status' into 'master'
Update group sharing status when creator joins group

Closes #850

See merge request briar/briar!1046
2019-02-27 11:34:55 +00:00
Torsten Grote
f6ef48bf90 [android] Fix private group status text over remove button 2019-02-26 11:38:17 -03:00
Torsten Grote
e282ca763d [android] Update group sharing status when creator joins group 2019-02-26 11:29:23 -03:00
Torsten Grote
71016382dc Merge branch 'tor-0.3.5.8' into 'master'
Upgrade Tor to 0.3.5.8

See merge request briar/briar!1045
2019-02-26 13:15:22 +00:00
akwizgran
d004933fae Upgrade Tor to 0.3.5.8. 2019-02-26 12:39:47 +00:00
akwizgran
37512c50d8 Merge branch '1497-foreground-permission' into 'master'
Add FOREGROUND_SERVICE permission (needed when targeting higher API level)

See merge request briar/briar!1041
2019-02-21 10:30:10 +00:00
Torsten Grote
0b61a5d40a Add FOREGROUND_SERVICE permission (needed when targeting higher API level) 2019-02-20 11:00:15 -03:00
akwizgran
5dd320f282 Merge branch '1498-meek' into 'master'
Use the pluggable transport meek lite where obfs4 is blocked

Closes #1498 and #1418

See merge request briar/briar!1040
2019-02-19 17:37:13 +00:00
akwizgran
2a21db5fb6 Merge branch 'tor-0.3.5.7' into 'master'
Upgrade Tor to 0.3.5.7

See merge request briar/briar!1039
2019-02-19 16:37:30 +00:00
Torsten Grote
b023593a2c Use the pluggable transport meek lite where obfs4 is blocked 2019-02-19 12:49:22 -03:00
Torsten Grote
5ccf2cae1f Upgrade Tor to 0.3.5.7 2019-02-19 11:09:45 -03:00
Torsten Grote
c2cb89ab73 [android] show the status bar when finishing ImageActivity
to prevent visible jump in exit transition.
2019-02-13 16:54:16 -02:00
42 changed files with 370 additions and 129 deletions

View File

@@ -39,31 +39,6 @@
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings> </JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
<XML> <XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" /> <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML> </XML>

View File

@@ -30,8 +30,8 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.3.4.8@zip' tor 'org.briarproject:tor-android:0.3.5.8@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.7@zip' tor 'org.briarproject:obfs4proxy-android:0.0.9@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19' annotationProcessor 'com.google.dagger:dagger-compiler:2.19'

View File

@@ -68,8 +68,8 @@ dependencyVerification {
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca', 'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.7:obfs4proxy-android-0.0.7.zip:abdfb5d889d848de9bf214f9276abbf454808a505b870819eccc9a9e985bf617', 'org.briarproject:obfs4proxy-android:0.0.9:obfs4proxy-android-0.0.9.zip:9b7e9181535ea8d8bbe8ae6338e08cf4c5fc1e357a779393e0ce49586d459ae0',
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926', 'org.briarproject:tor-android:0.3.5.8:tor-android-0.3.5.8.zip:42a13a6f185be1a62f42e3f30ce66a3c099ac5ec890a65e7593111b65b44a54a',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4', 'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d', 'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ContactExchangeListener {
void contactExchangeSucceeded(Author remoteAuthor);
/**
* The exchange failed because the contact already exists.
*/
void duplicateContact(Author remoteAuthor);
/**
* A general failure.
*/
void contactExchangeFailed();
}

View File

@@ -41,8 +41,7 @@ public interface ContactExchangeTask {
/** /**
* Exchanges contact information with a remote peer. * Exchanges contact information with a remote peer.
*/ */
void startExchange(ContactExchangeListener listener, void startExchange(LocalAuthor localAuthor, SecretKey masterSecret,
LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId, DuplexTransportConnection conn, TransportId transportId,
boolean alice); boolean alice);
} }

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public class ContactExchangeFailedEvent extends Event {
@Nullable
private final Author duplicateRemoteAuthor;
public ContactExchangeFailedEvent(@Nullable Author duplicateRemoteAuthor) {
this.duplicateRemoteAuthor = duplicateRemoteAuthor;
}
public ContactExchangeFailedEvent() {
this(null);
}
@Nullable
public Author getDuplicateRemoteAuthor() {
return duplicateRemoteAuthor;
}
public boolean wasDuplicateContact() {
return duplicateRemoteAuthor != null;
}
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class ContactExchangeSucceededEvent extends Event {
private final Author remoteAuthor;
public ContactExchangeSucceededEvent(Author remoteAuthor) {
this.remoteAuthor = remoteAuthor;
}
public Author getRemoteAuthor() {
return remoteAuthor;
}
}

View File

@@ -2,10 +2,11 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
@@ -13,6 +14,7 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -63,6 +65,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final RecordReaderFactory recordReaderFactory; private final RecordReaderFactory recordReaderFactory;
private final RecordWriterFactory recordWriterFactory; private final RecordWriterFactory recordWriterFactory;
private final EventBus eventBus;
private final Clock clock; private final Clock clock;
private final ConnectionManager connectionManager; private final ConnectionManager connectionManager;
private final ContactManager contactManager; private final ContactManager contactManager;
@@ -71,7 +74,6 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private final StreamReaderFactory streamReaderFactory; private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory; private final StreamWriterFactory streamWriterFactory;
private volatile ContactExchangeListener listener;
private volatile LocalAuthor localAuthor; private volatile LocalAuthor localAuthor;
private volatile DuplexTransportConnection conn; private volatile DuplexTransportConnection conn;
private volatile TransportId transportId; private volatile TransportId transportId;
@@ -81,8 +83,9 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
@Inject @Inject
ContactExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper, ContactExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper,
RecordReaderFactory recordReaderFactory, RecordReaderFactory recordReaderFactory,
RecordWriterFactory recordWriterFactory, Clock clock, RecordWriterFactory recordWriterFactory, EventBus eventBus,
ConnectionManager connectionManager, ContactManager contactManager, Clock clock, ConnectionManager connectionManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
CryptoComponent crypto, StreamReaderFactory streamReaderFactory, CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory) { StreamWriterFactory streamWriterFactory) {
@@ -90,6 +93,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.recordReaderFactory = recordReaderFactory; this.recordReaderFactory = recordReaderFactory;
this.recordWriterFactory = recordWriterFactory; this.recordWriterFactory = recordWriterFactory;
this.eventBus = eventBus;
this.clock = clock; this.clock = clock;
this.connectionManager = connectionManager; this.connectionManager = connectionManager;
this.contactManager = contactManager; this.contactManager = contactManager;
@@ -100,11 +104,9 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
} }
@Override @Override
public void startExchange(ContactExchangeListener listener, public void startExchange(LocalAuthor localAuthor, SecretKey masterSecret,
LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId, DuplexTransportConnection conn, TransportId transportId,
boolean alice) { boolean alice) {
this.listener = listener;
this.localAuthor = localAuthor; this.localAuthor = localAuthor;
this.conn = conn; this.conn = conn;
this.transportId = transportId; this.transportId = transportId;
@@ -123,8 +125,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
out = conn.getWriter().getOutputStream(); out = conn.getWriter().getOutputStream();
} catch (IOException e) { } catch (IOException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
listener.contactExchangeFailed();
tryToClose(conn); tryToClose(conn);
eventBus.broadcast(new ContactExchangeFailedEvent());
return; return;
} }
@@ -134,7 +136,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
localProperties = transportPropertyManager.getLocalProperties(); localProperties = transportPropertyManager.getLocalProperties();
} catch (DbException e) { } catch (DbException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
listener.contactExchangeFailed(); eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn); tryToClose(conn);
return; return;
} }
@@ -196,7 +198,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
} }
} catch (IOException e) { } catch (IOException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
listener.contactExchangeFailed(); eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn); tryToClose(conn);
return; return;
} }
@@ -204,7 +206,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
// Verify the contact's signature // Verify the contact's signature
if (!verify(remoteInfo.author, remoteNonce, remoteInfo.signature)) { if (!verify(remoteInfo.author, remoteNonce, remoteInfo.signature)) {
LOG.warning("Invalid signature"); LOG.warning("Invalid signature");
listener.contactExchangeFailed(); eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn); tryToClose(conn);
return; return;
} }
@@ -221,15 +223,17 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
conn); conn);
// Pseudonym exchange succeeded // Pseudonym exchange succeeded
LOG.info("Pseudonym exchange succeeded"); LOG.info("Pseudonym exchange succeeded");
listener.contactExchangeSucceeded(remoteInfo.author); eventBus.broadcast(
new ContactExchangeSucceededEvent(remoteInfo.author));
} catch (ContactExistsException e) { } catch (ContactExistsException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
tryToClose(conn); tryToClose(conn);
listener.duplicateContact(remoteInfo.author); eventBus.broadcast(
new ContactExchangeFailedEvent(remoteInfo.author));
} catch (DbException e) { } catch (DbException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
tryToClose(conn); tryToClose(conn);
listener.contactExchangeFailed(); eventBus.broadcast(new ContactExchangeFailedEvent());
} }
} }

View File

@@ -17,16 +17,24 @@ public interface CircumventionProvider {
String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"}; String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"};
/** /**
* Countries where vanilla bridge connection are likely to work. * Countries where obfs4 bridge connection are likely to work.
* Should be a subset of {@link #BLOCKED}. * Should be a subset of {@link #BLOCKED}.
*/ */
String[] BRIDGES = { "EG", "BY", "TR", "SY", "VE" }; String[] BRIDGES = { "CN", "IR", "EG", "BY", "TR", "SY", "VE" };
/**
* Countries where obfs4 bridges won't work and meek is needed.
* Should be a subset of {@link #BRIDGES}.
*/
String[] NEEDS_MEEK = {"CN", "IR"};
boolean isTorProbablyBlocked(String countryCode); boolean isTorProbablyBlocked(String countryCode);
boolean doBridgesWork(String countryCode); boolean doBridgesWork(String countryCode);
boolean needsMeek(String countryCode);
@IoExecutor @IoExecutor
List<String> getBridges(); List<String> getBridges(boolean meek);
} }

View File

@@ -22,6 +22,8 @@ class CircumventionProviderImpl implements CircumventionProvider {
new HashSet<>(asList(BLOCKED)); new HashSet<>(asList(BLOCKED));
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES = private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(asList(BRIDGES)); new HashSet<>(asList(BRIDGES));
private static final Set<String> BRIDGES_NEED_MEEK =
new HashSet<>(asList(NEEDS_MEEK));
@Nullable @Nullable
private volatile List<String> bridges = null; private volatile List<String> bridges = null;
@@ -40,9 +42,14 @@ class CircumventionProviderImpl implements CircumventionProvider {
return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode); return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode);
} }
@Override
public boolean needsMeek(String countryCode) {
return BRIDGES_NEED_MEEK.contains(countryCode);
}
@Override @Override
@IoExecutor @IoExecutor
public List<String> getBridges() { public List<String> getBridges(boolean useMeek) {
List<String> bridges = this.bridges; List<String> bridges = this.bridges;
if (bridges != null) return new ArrayList<>(bridges); if (bridges != null) return new ArrayList<>(bridges);
@@ -53,6 +60,8 @@ class CircumventionProviderImpl implements CircumventionProvider {
bridges = new ArrayList<>(); bridges = new ArrayList<>();
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
boolean isMeekBridge = line.startsWith("Bridge meek");
if (useMeek && !isMeekBridge || !useMeek && isMeekBridge) continue;
if (!line.startsWith("#")) bridges.add(line); if (!line.startsWith("#")) bridges.add(line);
} }
scanner.close(); scanner.close();

View File

@@ -470,13 +470,19 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (!enable) callback.transportDisabled(); if (!enable) callback.transportDisabled();
} }
private void enableBridges(boolean enable) throws IOException { private void enableBridges(boolean enable, boolean needsMeek)
throws IOException {
if (enable) { if (enable) {
Collection<String> conf = new ArrayList<>(); Collection<String> conf = new ArrayList<>();
conf.add("UseBridges 1"); conf.add("UseBridges 1");
conf.add("ClientTransportPlugin obfs4 exec " + if (needsMeek) {
obfs4File.getAbsolutePath()); conf.add("ClientTransportPlugin meek_lite exec " +
conf.addAll(circumventionProvider.getBridges()); obfs4File.getAbsolutePath());
} else {
conf.add("ClientTransportPlugin obfs4 exec " +
obfs4File.getAbsolutePath());
}
conf.addAll(circumventionProvider.getBridges(needsMeek));
controlConnection.setConf(conf); controlConnection.setConf(conf);
} else { } else {
controlConnection.setConf("UseBridges", "0"); controlConnection.setConf("UseBridges", "0");
@@ -716,12 +722,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
enableNetwork(false); enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_WITH_BRIDGES || } else if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
(automatic && bridgesWork)) { (automatic && bridgesWork)) {
LOG.info("Enabling network, using bridges"); if (circumventionProvider.needsMeek(country)) {
enableBridges(true); LOG.info("Enabling network, using meek bridges");
enableBridges(true, true);
} else {
LOG.info("Enabling network, using obfs4 bridges");
enableBridges(true, false);
}
enableNetwork(true); enableNetwork(true);
} else { } else {
LOG.info("Enabling network, not using bridges"); LOG.info("Enabling network, not using bridges");
enableBridges(false); enableBridges(false, false);
enableNetwork(true); enableNetwork(true);
} }
if (online && wifi && charging) { if (online && wifi && charging) {

View File

@@ -1,4 +1,5 @@
Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0 Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0
Bridge obfs4 52.15.78.72:9443 02069A3C5362476936B62BA6F5ACC41ABD573A9B cert=ijYG/OKc7kqu2YzKNFfeXN7/BG2BOgfEP2KyYEiGDQthnHbsOiTWHeIG0WJVW+BckzDgKw iat-mode=0 Bridge obfs4 52.15.78.72:9443 02069A3C5362476936B62BA6F5ACC41ABD573A9B cert=ijYG/OKc7kqu2YzKNFfeXN7/BG2BOgfEP2KyYEiGDQthnHbsOiTWHeIG0WJVW+BckzDgKw iat-mode=0
Bridge obfs4 13.58.29.242:9443 0C58939A77DA6B6B29D4B5236A75865659607AE0 cert=OylWIEHb/ezpq1zWxW0sgKRn+9ARH2eOcQOZ8/Gew+4l+oKOhQ2jUX/Y+FSl61JorXZUWA iat-mode=0 Bridge obfs4 13.58.29.242:9443 0C58939A77DA6B6B29D4B5236A75865659607AE0 cert=OylWIEHb/ezpq1zWxW0sgKRn+9ARH2eOcQOZ8/Gew+4l+oKOhQ2jUX/Y+FSl61JorXZUWA iat-mode=0
Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0 Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0
Bridge meek_lite 0.0.2.0:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@@ -16,7 +16,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
implementation 'net.java.dev.jna:jna:4.5.2' implementation 'net.java.dev.jna:jna:4.5.2'
implementation 'net.java.dev.jna:jna-platform:4.5.2' implementation 'net.java.dev.jna:jna-platform:4.5.2'
tor 'org.briarproject:tor:0.3.4.8@zip' tor 'org.briarproject:tor:0.3.5.8@zip'
tor 'org.briarproject:obfs4proxy:0.0.7@zip' tor 'org.briarproject:obfs4proxy:0.0.7@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19' annotationProcessor 'com.google.dagger:dagger-compiler:2.19'

View File

@@ -44,7 +44,7 @@ public class BridgeTest extends BrambleTestCase {
public static Iterable<String> data() { public static Iterable<String> data() {
BrambleJavaIntegrationTestComponent component = BrambleJavaIntegrationTestComponent component =
DaggerBrambleJavaIntegrationTestComponent.builder().build(); DaggerBrambleJavaIntegrationTestComponent.builder().build();
return component.getCircumventionProvider().getBridges(); return component.getCircumventionProvider().getBridges(false);
} }
private final static long TIMEOUT = SECONDS.toMillis(30); private final static long TIMEOUT = SECONDS.toMillis(30);
@@ -104,7 +104,12 @@ public class BridgeTest extends BrambleTestCase {
} }
@Override @Override
public List<String> getBridges() { public boolean needsMeek(String countryCode) {
return false;
}
@Override
public List<String> getBridges(boolean useMeek) {
return singletonList(bridge); return singletonList(bridge);
} }
}; };

View File

@@ -21,7 +21,7 @@ dependencyVerification {
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8', 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.briarproject:obfs4proxy:0.0.7:obfs4proxy-0.0.7.zip:5b2f693262ce43a7e130f7cc7d5d1617925330640a2eb6d71085e95df8ee0642', 'org.briarproject:obfs4proxy:0.0.7:obfs4proxy-0.0.7.zip:5b2f693262ce43a7e130f7cc7d5d1617925330640a2eb6d71085e95df8ee0642',
'org.briarproject:tor:0.3.4.8:tor-0.3.4.8.zip:bc0158c34002f471a4fe14a6a481816c918eb520a220bb027f64be902beb757f', 'org.briarproject:tor:0.3.5.8:tor-0.3.5.8.zip:96e83391f01984f28669235fc02fbb0243140a2b3b2c73aeffd0042c8d3ced18',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d', 'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',

View File

@@ -22,6 +22,7 @@
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" /> <uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:name="org.briarproject.briar.android.BriarApplicationImpl" android:name="org.briarproject.briar.android.BriarApplicationImpl"

View File

@@ -67,6 +67,10 @@ public class ImageActivity extends BriarActivity
final static String NAME = "name"; final static String NAME = "name";
final static String DATE = "date"; final static String DATE = "date";
@RequiresApi(api = 16)
private final static int UI_FLAGS_DEFAULT =
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
@Inject @Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
@@ -138,9 +142,7 @@ public class ImageActivity extends BriarActivity
if (SDK_INT >= 16) { if (SDK_INT >= 16) {
viewModel.getOnImageClicked().observe(this, this::onImageClicked); viewModel.getOnImageClicked().observe(this, this::onImageClicked);
window.getDecorView().setSystemUiVisibility( window.getDecorView().setSystemUiVisibility(UI_FLAGS_DEFAULT);
SYSTEM_UI_FLAG_LAYOUT_STABLE |
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} }
} }
@@ -206,9 +208,16 @@ public class ImageActivity extends BriarActivity
@Override @Override
public void onPullComplete() { public void onPullComplete() {
showStatusBarBeforeFinishing();
supportFinishAfterTransition(); supportFinishAfterTransition();
} }
@Override
public void onBackPressed() {
showStatusBarBeforeFinishing();
super.onBackPressed();
}
@RequiresApi(api = 16) @RequiresApi(api = 16)
private void onImageClicked(@Nullable Boolean clicked) { private void onImageClicked(@Nullable Boolean clicked) {
if (clicked != null && clicked) { if (clicked != null && clicked) {
@@ -229,9 +238,8 @@ public class ImageActivity extends BriarActivity
@RequiresApi(api = 16) @RequiresApi(api = 16)
private void hideSystemUi(View decorView) { private void hideSystemUi(View decorView) {
decorView.setSystemUiVisibility(SYSTEM_UI_FLAG_FULLSCREEN | decorView.setSystemUiVisibility(
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN SYSTEM_UI_FLAG_FULLSCREEN | UI_FLAGS_DEFAULT);
);
appBarLayout.animate() appBarLayout.animate()
.translationYBy(-1 * appBarLayout.getHeight()) .translationYBy(-1 * appBarLayout.getHeight())
.alpha(0f) .alpha(0f)
@@ -241,9 +249,7 @@ public class ImageActivity extends BriarActivity
@RequiresApi(api = 16) @RequiresApi(api = 16)
private void showSystemUi(View decorView) { private void showSystemUi(View decorView) {
decorView.setSystemUiVisibility( decorView.setSystemUiVisibility(UI_FLAGS_DEFAULT);
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
appBarLayout.animate() appBarLayout.animate()
.translationYBy(appBarLayout.getHeight()) .translationYBy(appBarLayout.getHeight())
.alpha(1f) .alpha(1f)
@@ -251,6 +257,18 @@ public class ImageActivity extends BriarActivity
.start(); .start();
} }
/**
* If we don't show the status bar again before finishing this activity,
* the return transition will "jump" down the size of the status bar
* when the previous activity (with visible status bar) is shown.
*/
private void showStatusBarBeforeFinishing() {
if (SDK_INT >= 16 && appBarLayout.getVisibility() == GONE) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(UI_FLAGS_DEFAULT);
}
}
private void showSaveImageDialog() { private void showSaveImageDialog() {
OnClickListener okListener = (dialog, which) -> { OnClickListener okListener = (dialog, which) -> {
if (SDK_INT >= 19) { if (SDK_INT >= 19) {

View File

@@ -4,9 +4,12 @@ import android.os.Bundle;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.widget.Toast; import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -28,7 +31,7 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ContactExchangeActivity extends KeyAgreementActivity implements public class ContactExchangeActivity extends KeyAgreementActivity implements
ContactExchangeListener { EventListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ContactExchangeActivity.class.getName()); Logger.getLogger(ContactExchangeActivity.class.getName());
@@ -50,6 +53,20 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
getSupportActionBar().setTitle(R.string.add_contact_title); getSupportActionBar().setTitle(R.string.add_contact_title);
} }
@Override
public void onStart() {
super.onStart();
// Listen to updates from contactExchangeTask
eventBus.addListener(this);
}
@Override
protected void onStop() {
super.onStop();
// Stop listen to updates from contactExchangeTask
eventBus.addListener(this);
}
private void startContactExchange(KeyAgreementResult result) { private void startContactExchange(KeyAgreementResult result) {
runOnDbThread(() -> { runOnDbThread(() -> {
LocalAuthor localAuthor; LocalAuthor localAuthor;
@@ -63,15 +80,28 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
} }
// Exchange contact details // Exchange contact details
contactExchangeTask.startExchange(ContactExchangeActivity.this, contactExchangeTask.startExchange(localAuthor,
localAuthor, result.getMasterKey(), result.getMasterKey(), result.getConnection(),
result.getConnection(), result.getTransportId(), result.getTransportId(), result.wasAlice());
result.wasAlice());
}); });
} }
@Override @Override
public void contactExchangeSucceeded(Author remoteAuthor) { public void eventOccurred(Event e) {
if (e instanceof ContactExchangeSucceededEvent) {
contactExchangeSucceeded(
((ContactExchangeSucceededEvent) e).getRemoteAuthor());
} else if (e instanceof ContactExchangeFailedEvent) {
ContactExchangeFailedEvent fe = (ContactExchangeFailedEvent) e;
if (fe.wasDuplicateContact()) {
duplicateContact(fe.getDuplicateRemoteAuthor());
} else {
contactExchangeFailed();
}
}
}
private void contactExchangeSucceeded(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName(); String contactName = remoteAuthor.getName();
String format = getString(R.string.contact_added_toast); String format = getString(R.string.contact_added_toast);
@@ -82,8 +112,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
}); });
} }
@Override private void duplicateContact(Author remoteAuthor) {
public void duplicateContact(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName(); String contactName = remoteAuthor.getName();
String format = getString(R.string.contact_already_exists); String format = getString(R.string.contact_already_exists);
@@ -94,8 +123,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
}); });
} }
@Override private void contactExchangeFailed() {
public void contactExchangeFailed() {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
showErrorFragment(R.string.connection_error_explanation); showErrorFragment(R.string.connection_error_explanation);
}); });

View File

@@ -178,6 +178,14 @@ public class GroupActivity extends
} else super.onActivityResult(request, result, data); } else super.onActivityResult(request, result, data);
} }
@Override
public void onItemReceived(GroupMessageItem item) {
super.onItemReceived(item);
if (item instanceof JoinMessageItem) {
if (((JoinMessageItem) item).isInitial()) loadSharingContacts();
}
}
@Override @Override
protected int getMaxTextLength() { protected int getMaxTextLength() {
return MAX_GROUP_POST_TEXT_LENGTH; return MAX_GROUP_POST_TEXT_LENGTH;

View File

@@ -7,14 +7,20 @@ import android.view.MenuItem;
import android.widget.TextView; import android.widget.TextView;
import org.briarproject.bramble.api.db.DbException; 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.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.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
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;
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler; import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
import java.util.Collection; import java.util.Collection;
@@ -23,10 +29,13 @@ import javax.inject.Inject;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class GroupMemberListActivity extends BriarActivity { public class GroupMemberListActivity extends BriarActivity
implements EventListener {
@Inject @Inject
GroupMemberListController controller; GroupMemberListController controller;
@Inject
EventBus eventBus;
private MemberListAdapter adapter; private MemberListAdapter adapter;
private BriarRecyclerView list; private BriarRecyclerView list;
@@ -61,28 +70,38 @@ public class GroupMemberListActivity extends BriarActivity {
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
controller.loadMembers(groupId, loadMembers();
new UiResultExceptionHandler<Collection<MemberListItem>, DbException>( eventBus.addListener(this);
this) {
@Override
public void onResultUi(Collection<MemberListItem> members) {
adapter.addAll(members);
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
}
});
list.startPeriodicUpdate(); list.startPeriodicUpdate();
} }
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
eventBus.removeListener(this);
list.stopPeriodicUpdate(); list.stopPeriodicUpdate();
} }
@Override
public void eventOccurred(Event e) {
if (e instanceof GroupMessageAddedEvent) {
// we can't use GroupInvitationResponseReceivedEvent, because
// a peer only becomes a member after joining the group by message
GroupMessageAddedEvent ge = (GroupMessageAddedEvent) e;
if (ge.getGroupId().equals(groupId) &&
ge.getHeader() instanceof JoinMessageHeader) {
loadMembers();
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getId().equals(groupId)) {
runOnUiThreadUnlessDestroyed(
this::supportFinishAfterTransition);
}
}
// TODO ContactConnectedEvent and ContactDisconnectedEvent
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@@ -94,4 +113,20 @@ public class GroupMemberListActivity extends BriarActivity {
} }
} }
private void loadMembers() {
controller.loadMembers(groupId,
new UiResultExceptionHandler<Collection<MemberListItem>, DbException>(
this) {
@Override
public void onResultUi(Collection<MemberListItem> members) {
adapter.addAll(members);
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
}
});
}
} }

View File

@@ -3,11 +3,14 @@ package org.briarproject.briar.android.sharing;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
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.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.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import java.util.Collection; import java.util.Collection;
@@ -26,6 +29,19 @@ public class BlogSharingStatusActivity extends SharingStatusActivity {
component.inject(this); component.inject(this);
} }
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent r =
(BlogInvitationResponseReceivedEvent) e;
BlogInvitationResponse h = r.getMessageHeader();
if (h.getShareableId().equals(getGroupId()) && h.wasAccepted()) {
loadSharedWith();
}
}
}
@Override @Override
int getInfoText() { int getInfoText() {
return R.string.sharing_status_blog; return R.string.sharing_status_blog;

View File

@@ -3,11 +3,14 @@ package org.briarproject.briar.android.sharing;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
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.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.api.forum.ForumInvitationResponse;
import org.briarproject.briar.api.forum.ForumSharingManager; import org.briarproject.briar.api.forum.ForumSharingManager;
import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent;
import java.util.Collection; import java.util.Collection;
@@ -26,6 +29,19 @@ public class ForumSharingStatusActivity extends SharingStatusActivity {
component.inject(this); component.inject(this);
} }
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof ForumInvitationResponseReceivedEvent) {
ForumInvitationResponseReceivedEvent r =
(ForumInvitationResponseReceivedEvent) e;
ForumInvitationResponse h = r.getMessageHeader();
if (h.getShareableId().equals(getGroupId()) && h.wasAccepted()) {
loadSharedWith();
}
}
}
@Override @Override
int getInfoText() { int getInfoText() {
return R.string.sharing_status_forum; return R.string.sharing_status_forum;

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android.sharing;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.view.MenuItem; import android.view.MenuItem;
@@ -10,14 +11,19 @@ import android.widget.TextView;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; 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.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.ConnectionRegistry; import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contact.ContactItem; import org.briarproject.briar.android.contact.ContactItem;
import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -32,10 +38,13 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
abstract class SharingStatusActivity extends BriarActivity { abstract class SharingStatusActivity extends BriarActivity
implements EventListener {
@Inject @Inject
ConnectionRegistry connectionRegistry; ConnectionRegistry connectionRegistry;
@Inject
EventBus eventBus;
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SharingStatusActivity.class.getName()); Logger.getLogger(SharingStatusActivity.class.getName());
@@ -68,6 +77,7 @@ abstract class SharingStatusActivity extends BriarActivity {
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
eventBus.addListener(this);
loadSharedWith(); loadSharedWith();
} }
@@ -75,9 +85,28 @@ abstract class SharingStatusActivity extends BriarActivity {
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
adapter.clear(); adapter.clear();
eventBus.removeListener(this);
list.showProgressBar(); list.showProgressBar();
} }
@Override
@CallSuper
public void eventOccurred(Event e) {
if (e instanceof ContactLeftShareableEvent) {
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
if (c.getGroupId().equals(getGroupId())) {
loadSharedWith();
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getId().equals(getGroupId())) {
runOnUiThreadUnlessDestroyed(
this::supportFinishAfterTransition);
}
}
// TODO ContactConnectedEvent and ContactDisconnectedEvent
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items // Handle presses on the action bar items
@@ -100,7 +129,7 @@ abstract class SharingStatusActivity extends BriarActivity {
return groupId; return groupId;
} }
private void loadSharedWith() { protected void loadSharedWith() {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
List<ContactItem> contactItems = new ArrayList<>(); List<ContactItem> contactItems = new ArrayList<>();
@@ -118,6 +147,7 @@ abstract class SharingStatusActivity extends BriarActivity {
private void displaySharedWith(List<ContactItem> contacts) { private void displaySharedWith(List<ContactItem> contacts) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
adapter.clear();
if (contacts.isEmpty()) list.showData(); if (contacts.isEmpty()) list.showData();
else adapter.addAll(contacts); else adapter.addAll(contacts);
}); });

View File

@@ -82,11 +82,11 @@
android:layout_marginStart="@dimen/listitem_horizontal_margin" android:layout_marginStart="@dimen/listitem_horizontal_margin"
android:layout_marginTop="@dimen/margin_medium" android:layout_marginTop="@dimen/margin_medium"
android:textColor="?android:attr/textColorTertiary" android:textColor="?android:attr/textColorTertiary"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/removeButton"
app:layout_constraintLeft_toRightOf="@+id/avatarView" app:layout_constraintLeft_toRightOf="@+id/avatarView"
app:layout_constraintStart_toEndOf="@+id/avatarView" app:layout_constraintStart_toEndOf="@+id/avatarView"
app:layout_constraintTop_toBottomOf="@+id/messageCountView" app:layout_constraintTop_toBottomOf="@+id/messageCountView"
tools:text="@string/groups_group_is_empty"/> tools:text="This group is empty, but has a long status text"/>
<Button <Button
android:id="@+id/removeButton" android:id="@+id/removeButton"
@@ -94,9 +94,11 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/groups_remove" android:text="@string/groups_remove"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/divider" app:layout_constraintBottom_toBottomOf="@+id/divider"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
tools:visibility="gone"/> app:layout_constraintTop_toTopOf="@+id/statusView"
tools:visibility="visible"/>
<View <View
android:id="@+id/divider" android:id="@+id/divider"

View File

@@ -13,7 +13,7 @@
android:id="@+id/action_group_member_list" android:id="@+id/action_group_member_list"
android:icon="@drawable/ic_group_white" android:icon="@drawable/ic_group_white"
android:title="@string/groups_member_list" android:title="@string/groups_member_list"
app:showAsAction="ifRoom"/> app:showAsAction="never"/>
<item <item
android:id="@+id/action_group_reveal" android:id="@+id/action_group_reveal"

View File

@@ -1,6 +1,7 @@
package org.briarproject.briar.messaging; package org.briarproject.briar.messaging;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
@@ -32,11 +33,12 @@ import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent; import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.client.ConversationClientImpl; import org.briarproject.briar.client.ConversationClientImpl;
import java.io.ByteArrayInputStream; import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@@ -44,7 +46,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static org.briarproject.bramble.util.StringUtils.fromHexString; import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
@Immutable @Immutable
@@ -219,8 +221,26 @@ class MessagingManagerImpl extends ConversationClientImpl
long timestamp = meta.getLong("timestamp"); long timestamp = meta.getLong("timestamp");
boolean local = meta.getBoolean("local"); boolean local = meta.getBoolean("local");
boolean read = meta.getBoolean("read"); boolean read = meta.getBoolean("read");
// TODO replace fake attachments by real ones
boolean hasText;
List<AttachmentHeader> attachments;
Random random = new Random(id.hashCode());
if (random.nextBoolean()) {
hasText = random.nextBoolean();
attachments = new ArrayList<>();
int numAttachments = random.nextInt(10) + 1;
for (int i = 0; i < numAttachments; i++) {
byte[] b = new byte[UniqueId.LENGTH];
random.nextBytes(b);
attachments.add(new AttachmentHeader(new MessageId(b),
"image/jpeg"));
}
} else {
hasText = true;
attachments = emptyList();
}
headers.add(new PrivateMessageHeader(id, g, timestamp, local, headers.add(new PrivateMessageHeader(id, g, timestamp, local,
read, s.isSent(), s.isSeen(), true, emptyList())); read, s.isSent(), s.isSeen(), hasText, attachments));
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
@@ -241,11 +261,30 @@ class MessagingManagerImpl extends ConversationClientImpl
@Override @Override
public Attachment getAttachment(MessageId m) { public Attachment getAttachment(MessageId m) {
// TODO add real implementation // TODO add real implementation
byte[] bytes = fromHexString("89504E470D0A1A0A0000000D49484452" + String[] files = new String[] {
"000000010000000108060000001F15C4" + // "error_animated.gif",
"890000000A49444154789C6300010000" + // "error_high.jpg",
"0500010D0A2DB40000000049454E44AE426082"); // "error_wide.jpg",
return new Attachment(new ByteArrayInputStream(bytes)); // "error_huge.gif",
// "error_large.gif",
// "error_malformed.jpg",
// "wide.jpg",
// "high.jpg",
// "small.png",
"kitten1.jpg",
"kitten2.jpg",
"kitten3.gif",
"kitten4.jpg",
"kitten5.jpg",
"kitten6.png",
};
int index = Math.abs(m.hashCode() % files.length);
String file = files[index];
getLogger(MessagingManagerImpl.class.getName())
.warning("Loading file: " + file);
InputStream is = getClass().getClassLoader().getResourceAsStream(file);
return new Attachment(new BufferedInputStream(is));
} }
@Override @Override

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -11,6 +11,10 @@ The REST API peer comes as a `jar` file
and needs a Java Runtime Environment (JRE) that supports at least Java 8. and needs a Java Runtime Environment (JRE) that supports at least Java 8.
It currently works only on GNU/Linux operating systems. It currently works only on GNU/Linux operating systems.
To build the `jar` file, you can do this:
$ ./gradlew --configure-on-demand briar-headless:jar
You can start the peer (and its API server) like this: You can start the peer (and its API server) like this:
$ java -jar briar-headless/build/libs/briar-headless.jar $ java -jar briar-headless/build/libs/briar-headless.jar