Merge branch 'master' into '2277-activity-not-found-exception'

# Conflicts:
#   briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageActivity.java
This commit is contained in:
akwizgran
2022-04-18 16:18:14 +00:00
11 changed files with 69 additions and 28 deletions

View File

@@ -32,13 +32,22 @@ class AndroidRemovableDrivePlugin extends RemovableDrivePlugin {
InputStream openInputStream(TransportProperties p) throws IOException { InputStream openInputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI); String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException(); if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openInputStream(Uri.parse(uri)); try {
return app.getContentResolver().openInputStream(Uri.parse(uri));
} catch (SecurityException e) {
throw new IOException(e);
}
} }
@Override @Override
OutputStream openOutputStream(TransportProperties p) throws IOException { OutputStream openOutputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI); String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException(); if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openOutputStream(Uri.parse(uri), "wt"); try {
return app.getContentResolver()
.openOutputStream(Uri.parse(uri), "wt");
} catch (SecurityException e) {
throw new IOException(e);
}
} }
} }

View File

@@ -116,10 +116,12 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
long dueMillis = now + MILLISECONDS.convert(delay, unit); long dueMillis = now + MILLISECONDS.convert(delay, unit);
Runnable wakeful = () -> Runnable wakeful = () ->
wakeLockManager.executeWakefully(task, executor, "TaskHandoff"); wakeLockManager.executeWakefully(task, executor, "TaskHandoff");
Future<?> check = scheduleCheckForDueTasks(delay, unit); // Acquire the lock before scheduling the check to ensure the check
ScheduledTask s = new ScheduledTask(wakeful, dueMillis, check, // doesn't access the task queue before the task has been added
cancelled); ScheduledTask s;
synchronized (lock) { synchronized (lock) {
Future<?> check = scheduleCheckForDueTasks(delay, unit);
s = new ScheduledTask(wakeful, dueMillis, check, cancelled);
tasks.add(s); tasks.add(s);
} }
return s; return s;
@@ -136,6 +138,7 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
return schedule(wrapped, executor, delay, unit, cancelled); return schedule(wrapped, executor, delay, unit, cancelled);
} }
@GuardedBy("lock")
private Future<?> scheduleCheckForDueTasks(long delay, TimeUnit unit) { private Future<?> scheduleCheckForDueTasks(long delay, TimeUnit unit) {
Runnable wakeful = () -> wakeLockManager.runWakefully( Runnable wakeful = () -> wakeLockManager.runWakefully(
this::runDueTasks, "TaskScheduler"); this::runDueTasks, "TaskScheduler");
@@ -206,7 +209,7 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
private final Future<?> check; private final Future<?> check;
private final AtomicBoolean cancelled; private final AtomicBoolean cancelled;
public ScheduledTask(Runnable task, long dueMillis, private ScheduledTask(Runnable task, long dueMillis,
Future<?> check, AtomicBoolean cancelled) { Future<?> check, AtomicBoolean cancelled) {
this.task = task; this.task = task;
this.dueMillis = dueMillis; this.dueMillis = dueMillis;

View File

@@ -1,5 +1,7 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin;
import static java.util.concurrent.TimeUnit.SECONDS;
public interface TorConstants { public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor"); TransportId ID = new TransportId("org.briarproject.bramble.tor");
@@ -10,8 +12,9 @@ public interface TorConstants {
int DEFAULT_SOCKS_PORT = 59050; int DEFAULT_SOCKS_PORT = 59050;
int DEFAULT_CONTROL_PORT = 59051; int DEFAULT_CONTROL_PORT = 59051;
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds int CONNECT_TO_PROXY_TIMEOUT = (int) SECONDS.toMillis(5);
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds int EXTRA_CONNECT_TIMEOUT = (int) SECONDS.toMillis(120);
int EXTRA_SOCKET_TIMEOUT = (int) SECONDS.toMillis(30);
// Local settings (not shared with contacts) // Local settings (not shared with contacts)
String PREF_TOR_NETWORK = "network2"; String PREF_TOR_NETWORK = "network2";

View File

@@ -10,6 +10,7 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT; import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_CONNECT_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_SOCKET_TIMEOUT; import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_SOCKET_TIMEOUT;
@Module @Module
@@ -20,6 +21,6 @@ public class SocksModule {
InetSocketAddress proxy = new InetSocketAddress("127.0.0.1", InetSocketAddress proxy = new InetSocketAddress("127.0.0.1",
torSocksPort); torSocksPort);
return new SocksSocketFactory(proxy, CONNECT_TO_PROXY_TIMEOUT, return new SocksSocketFactory(proxy, CONNECT_TO_PROXY_TIMEOUT,
EXTRA_SOCKET_TIMEOUT); EXTRA_CONNECT_TIMEOUT, EXTRA_SOCKET_TIMEOUT);
} }
} }

View File

@@ -26,15 +26,18 @@ class SocksSocket extends Socket {
"Address type not supported" "Address type not supported"
}; };
@SuppressWarnings("MismatchedReadAndWriteOfArray")
private static final byte[] UNSPECIFIED_ADDRESS = new byte[4]; private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];
private final SocketAddress proxy; private final SocketAddress proxy;
private final int connectToProxyTimeout, extraSocketTimeout; private final int connectToProxyTimeout;
private final int extraConnectTimeout, extraSocketTimeout;
SocksSocket(SocketAddress proxy, int connectToProxyTimeout, SocksSocket(SocketAddress proxy, int connectToProxyTimeout,
int extraSocketTimeout) { int extraConnectTimeout, int extraSocketTimeout) {
this.proxy = proxy; this.proxy = proxy;
this.connectToProxyTimeout = connectToProxyTimeout; this.connectToProxyTimeout = connectToProxyTimeout;
this.extraConnectTimeout = extraConnectTimeout;
this.extraSocketTimeout = extraSocketTimeout; this.extraSocketTimeout = extraSocketTimeout;
} }
@@ -66,7 +69,7 @@ class SocksSocket extends Socket {
// Use the supplied timeout temporarily, plus any configured extra // Use the supplied timeout temporarily, plus any configured extra
int oldTimeout = getSoTimeout(); int oldTimeout = getSoTimeout();
setSoTimeout(timeout + extraSocketTimeout); setSoTimeout(timeout + extraConnectTimeout);
// Connect to the endpoint via the proxy // Connect to the endpoint via the proxy
sendConnectRequest(out, host, port); sendConnectRequest(out, host, port);

View File

@@ -11,18 +11,21 @@ import javax.net.SocketFactory;
class SocksSocketFactory extends SocketFactory { class SocksSocketFactory extends SocketFactory {
private final SocketAddress proxy; private final SocketAddress proxy;
private final int connectToProxyTimeout, extraSocketTimeout; private final int connectToProxyTimeout;
private final int extraConnectTimeout, extraSocketTimeout;
SocksSocketFactory(SocketAddress proxy, int connectToProxyTimeout, SocksSocketFactory(SocketAddress proxy, int connectToProxyTimeout,
int extraSocketTimeout) { int extraConnectTimeout, int extraSocketTimeout) {
this.proxy = proxy; this.proxy = proxy;
this.connectToProxyTimeout = connectToProxyTimeout; this.connectToProxyTimeout = connectToProxyTimeout;
this.extraConnectTimeout = extraConnectTimeout;
this.extraSocketTimeout = extraSocketTimeout; this.extraSocketTimeout = extraSocketTimeout;
} }
@Override @Override
public Socket createSocket() { public Socket createSocket() {
return new SocksSocket(proxy, connectToProxyTimeout, extraSocketTimeout); return new SocksSocket(proxy, connectToProxyTimeout,
extraConnectTimeout, extraSocketTimeout);
} }
@Override @Override

View File

@@ -26,6 +26,7 @@ import static org.briarproject.bramble.util.IoUtils.tryToClose;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.android.attachment.media.ImageCompressor.MIME_TYPE;
@NotNullByDefault @NotNullByDefault
class AttachmentCreationTask { class AttachmentCreationTask {
@@ -100,14 +101,17 @@ class AttachmentCreationTask {
if (!asList(getSupportedImageContentTypes()).contains(contentType)) { if (!asList(getSupportedImageContentTypes()).contains(contentType)) {
throw new UnsupportedMimeTypeException(contentType, uri); throw new UnsupportedMimeTypeException(contentType, uri);
} }
InputStream is = contentResolver.openInputStream(uri); InputStream is;
if (is == null) throw new IOException(); try {
is = imageCompressor is = contentResolver.openInputStream(uri);
.compressImage(is, contentType); if (is == null) throw new IOException();
} catch (SecurityException e) {
throw new IOException(e);
}
is = imageCompressor.compressImage(is, contentType);
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
AttachmentHeader h = messagingManager AttachmentHeader h = messagingManager.addLocalAttachment(groupId,
.addLocalAttachment(groupId, timestamp, timestamp, MIME_TYPE, is);
ImageCompressor.MIME_TYPE, is);
tryToClose(is, LOG, WARNING); tryToClose(is, LOG, WARNING);
logDuration(LOG, "Storing attachment", start); logDuration(LOG, "Storing attachment", start);
return h; return h;

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.android.conversation; package org.briarproject.briar.android.conversation;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@@ -259,7 +260,11 @@ public class ImageActivity extends BriarActivity
if (SDK_INT >= 19) { if (SDK_INT >= 19) {
String name = viewModel.getFileName() + "." + String name = viewModel.getFileName() + "." +
getVisibleAttachment().getExtension(); getVisibleAttachment().getExtension();
requireNonNull(launcher).launch(name); try {
requireNonNull(launcher).launch(name);
} catch (ActivityNotFoundException e) {
viewModel.onSaveImageError();
}
} else { } else {
viewModel.saveImage(getVisibleAttachment()); viewModel.saveImage(getVisibleAttachment());
} }

View File

@@ -180,12 +180,17 @@ public class ImageViewModel extends DbViewModel implements EventListener {
@UiThread @UiThread
void saveImage(AttachmentItem attachment, @Nullable Uri uri) { void saveImage(AttachmentItem attachment, @Nullable Uri uri) {
if (uri == null) { if (uri == null) {
saveState.setEvent(true); onSaveImageError();
} else { } else {
saveImage(attachment, () -> getOutputStream(uri), null); saveImage(attachment, () -> getOutputStream(uri), null);
} }
} }
@UiThread
void onSaveImageError() {
saveState.setEvent(true);
}
/** /**
* Saves the attachment on external storage, * Saves the attachment on external storage,
* assuming the permission was granted during install time. * assuming the permission was granted during install time.

View File

@@ -231,9 +231,14 @@ class SettingsViewModel extends DbViewModel implements EventListener {
if (!asList(getSupportedImageContentTypes()).contains(contentType)) { if (!asList(getSupportedImageContentTypes()).contains(contentType)) {
throw new UnsupportedMimeTypeException(contentType, uri); throw new UnsupportedMimeTypeException(contentType, uri);
} }
InputStream is = contentResolver.openInputStream(uri); InputStream is;
if (is == null) throw new IOException( try {
"ContentResolver returned null when opening InputStream"); is = contentResolver.openInputStream(uri);
if (is == null) throw new IOException(
"ContentResolver returned null when opening InputStream");
} catch (SecurityException e) {
throw new IOException(e);
}
InputStream compressed = imageCompressor.compressImage(is, contentType); InputStream compressed = imageCompressor.compressImage(is, contentType);
runOnDbThread(() -> { runOnDbThread(() -> {

View File

@@ -320,7 +320,7 @@
<!-- Introductions --> <!-- Introductions -->
<string name="introduction_onboarding_title">Introduce your contacts</string> <string name="introduction_onboarding_title">Introduce your contacts</string>
<string name="introduction_onboarding_text">You can introduce your contacts to each other, so they don\'t need to meet in person to connect on Briar.</string> <string name="introduction_onboarding_text">Introduce your contacts to each other so they can connect on Briar.</string>
<string name="introduction_menu_item">Make Introduction</string> <string name="introduction_menu_item">Make Introduction</string>
<string name="introduction_activity_title">Select Contact</string> <string name="introduction_activity_title">Select Contact</string>
<string name="introduction_not_possible">You already have one introduction in progress with these contacts. Please allow for this to finish first. If you or your contacts are rarely online, this can take some time.</string> <string name="introduction_not_possible">You already have one introduction in progress with these contacts. Please allow for this to finish first. If you or your contacts are rarely online, this can take some time.</string>