Turned SingleUseBlobProvider into MemoryBlobProvider.

Keep the single-use behavior, but allow the creation of multi-use memory
blobs that can be deleted when we're done with them. Will help out with
having URI's for temporary images during the camera capture flow.
fork-5.53.8
Greyson Parrelli 2018-09-24 11:47:51 -07:00
rodzic e63773e5c8
commit e9a38bab1e
5 zmienionych plików z 98 dodań i 64 usunięć

Wyświetl plik

@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
import org.thoughtcrime.securesms.providers.MemoryBlobProvider;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.BitmapUtil;
@ -111,7 +111,7 @@ public class GroupManager {
GroupContext groupContext = groupContextBuilder.build();
if (avatar != null) {
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
Uri avatarUri = MemoryBlobProvider.getInstance().createSingleUseUri(avatar);
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false);
}

Wyświetl plik

@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsRadioException;
import org.thoughtcrime.securesms.mms.PartParser;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
import org.thoughtcrime.securesms.providers.MemoryBlobProvider;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
@ -174,7 +174,7 @@ public class MmsDownloadJob extends MasterSecretJob {
LegacyMessageException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
SingleUseBlobProvider provider = SingleUseBlobProvider.getInstance();
MemoryBlobProvider provider = MemoryBlobProvider.getInstance();
Optional<Address> group = Optional.absent();
Set<Address> members = new HashSet<>();
String body = null;
@ -213,7 +213,7 @@ public class MmsDownloadJob extends MasterSecretJob {
PduPart part = media.getPart(i);
if (part.getData() != null) {
Uri uri = provider.createUri(part.getData());
Uri uri = provider.createSingleUseUri(part.getData());
String name = null;
if (part.getName() != null) name = Util.toIsoString(part.getName());

Wyświetl plik

@ -9,11 +9,10 @@ import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.providers.PartProvider;
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
import org.thoughtcrime.securesms.providers.MemoryBlobProvider;
import java.io.IOException;
import java.io.InputStream;
@ -38,7 +37,7 @@ public class PartAuthority {
uriMatcher.addURI("org.thoughtcrime.securesms", "thumb/*/#", THUMB_ROW);
uriMatcher.addURI(PersistentBlobProvider.AUTHORITY, PersistentBlobProvider.EXPECTED_PATH_OLD, PERSISTENT_ROW);
uriMatcher.addURI(PersistentBlobProvider.AUTHORITY, PersistentBlobProvider.EXPECTED_PATH_NEW, PERSISTENT_ROW);
uriMatcher.addURI(SingleUseBlobProvider.AUTHORITY, SingleUseBlobProvider.PATH, SINGLE_USE_ROW);
uriMatcher.addURI(MemoryBlobProvider.AUTHORITY, MemoryBlobProvider.PATH, SINGLE_USE_ROW);
}
public static InputStream getAttachmentStream(@NonNull Context context, @NonNull Uri uri)
@ -50,7 +49,7 @@ public class PartAuthority {
case PART_ROW: return DatabaseFactory.getAttachmentDatabase(context).getAttachmentStream(new PartUriParser(uri).getPartId(), 0);
case THUMB_ROW: return DatabaseFactory.getAttachmentDatabase(context).getThumbnailStream(new PartUriParser(uri).getPartId());
case PERSISTENT_ROW: return PersistentBlobProvider.getInstance(context).getStream(context, ContentUris.parseId(uri));
case SINGLE_USE_ROW: return SingleUseBlobProvider.getInstance().getStream(ContentUris.parseId(uri));
case SINGLE_USE_ROW: return MemoryBlobProvider.getInstance().getStream(ContentUris.parseId(uri));
default: return context.getContentResolver().openInputStream(uri);
}
} catch (SecurityException se) {

Wyświetl plik

@ -0,0 +1,90 @@
package org.thoughtcrime.securesms.providers;
import android.content.ContentUris;
import android.net.Uri;
import android.support.annotation.NonNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
public class MemoryBlobProvider {
@SuppressWarnings("unused")
private static final String TAG = MemoryBlobProvider.class.getSimpleName();
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String PATH = "memory/*/#";
private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/memory");
private final Map<Long, Entry> cache = new HashMap<>();
private static final MemoryBlobProvider instance = new MemoryBlobProvider();
public static MemoryBlobProvider getInstance() {
return instance;
}
private MemoryBlobProvider() {}
public synchronized Uri createSingleUseUri(@NonNull byte[] blob) {
return createUriInternal(blob, true);
}
public synchronized Uri createUri(@NonNull byte[] blob) {
return createUriInternal(blob, false);
}
public synchronized void delete(@NonNull Uri uri) {
cache.remove(ContentUris.parseId(uri));
}
public synchronized @NonNull InputStream getStream(long id) throws IOException {
Entry entry = cache.get(id);
if (entry == null) {
throw new IOException("ID not found: " + id);
}
if (entry.isSingleUse()) {
cache.remove(id);
}
return new ByteArrayInputStream(entry.getBlob());
}
private Uri createUriInternal(@NonNull byte[] blob, boolean singleUse) {
try {
long id = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
cache.put(id, new Entry(blob, singleUse));
Uri uniqueUri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(System.currentTimeMillis()));
return ContentUris.withAppendedId(uniqueUri, id);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
private static class Entry {
private final byte[] blob;
private final boolean singleUse;
private Entry(@NonNull byte[] blob, boolean singleUse) {
this.blob = blob;
this.singleUse = singleUse;
}
public byte[] getBlob() {
return blob;
}
public boolean isSingleUse() {
return singleUse;
}
}
}

Wyświetl plik

@ -1,55 +0,0 @@
package org.thoughtcrime.securesms.providers;
import android.content.ContentUris;
import android.net.Uri;
import android.support.annotation.NonNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
public class SingleUseBlobProvider {
@SuppressWarnings("unused")
private static final String TAG = SingleUseBlobProvider.class.getSimpleName();
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String PATH = "memory/*/#";
private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/memory");
private final Map<Long, byte[]> cache = new HashMap<>();
private static final SingleUseBlobProvider instance = new SingleUseBlobProvider();
public static SingleUseBlobProvider getInstance() {
return instance;
}
private SingleUseBlobProvider() {}
public synchronized Uri createUri(@NonNull byte[] blob) {
try {
long id = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
cache.put(id, blob);
Uri uniqueUri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(System.currentTimeMillis()));
return ContentUris.withAppendedId(uniqueUri, id);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
public synchronized @NonNull InputStream getStream(long id) throws IOException {
byte[] cached = cache.get(id);
cache.remove(id);
if (cached != null) return new ByteArrayInputStream(cached);
else throw new IOException("ID not found: " + id);
}
}