Add MIME type to PersistentBlobProvider

Fixes #4536
Closes #4689
master
Geonu Kang 2015-11-21 16:18:19 +09:00 committed by Moxie Marlinspike
parent bf806bd717
commit a2f478570a
6 changed files with 68 additions and 35 deletions

View File

@ -1402,7 +1402,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onImageCapture(@NonNull final byte[] imageBytes) {
setMedia(PersistentBlobProvider.getInstance(this).create(masterSecret, imageBytes), MediaType.IMAGE);
setMedia(PersistentBlobProvider.getInstance(this)
.create(masterSecret, imageBytes, ContentType.IMAGE_JPEG),
MediaType.IMAGE);
quickAttachmentDrawer.hide(false);
}

View File

@ -23,6 +23,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@ -59,6 +60,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
private ViewGroup fragmentContainer;
private View progressWheel;
private Uri resolvedExtra;
private String mimeType;
private boolean isPassingAlongMedia;
@Override
@ -110,6 +112,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
isPassingAlongMedia = false;
Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
mimeType = getMimeType(streamExtra);
if (streamExtra != null && PartAuthority.isLocalUri(streamExtra)) {
isPassingAlongMedia = true;
resolvedExtra = streamExtra;
@ -166,19 +169,18 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
private Intent getBaseShareIntent(final @NonNull Class<?> target) {
final Intent intent = new Intent(this, target);
final String textExtra = getIntent().getStringExtra(Intent.EXTRA_TEXT);
final Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
final String type = streamExtra != null ? getMimeType(streamExtra)
: MediaUtil.getCorrectedMimeType(getIntent().getType());
intent.putExtra(ConversationActivity.TEXT_EXTRA, textExtra);
if (resolvedExtra != null) intent.setDataAndType(resolvedExtra, type);
if (resolvedExtra != null) intent.setDataAndType(resolvedExtra, mimeType);
return intent;
}
private String getMimeType(Uri uri) {
final String type = MediaUtil.getMimeType(getApplicationContext(), uri);
return type == null ? MediaUtil.getCorrectedMimeType(getIntent().getType())
: type;
private String getMimeType(@Nullable Uri uri) {
if (uri != null) {
final String mimeType = MediaUtil.getMimeType(getApplicationContext(), uri);
if (mimeType != null) return mimeType;
}
return MediaUtil.getCorrectedMimeType(getIntent().getType());
}
private class ResolveMediaTask extends AsyncTask<Uri, Void, Uri> {
@ -200,7 +202,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
return null;
}
return PersistentBlobProvider.getInstance(context).create(masterSecret, input);
return PersistentBlobProvider.getInstance(context).create(masterSecret, input, mimeType);
} catch (IOException ioe) {
Log.w(TAG, ioe);
return null;

View File

@ -20,6 +20,8 @@ import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import ws.com.google.android.mms.ContentType;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class AudioRecorder {
@ -54,7 +56,9 @@ public class AudioRecorder {
ParcelFileDescriptor fds[] = ParcelFileDescriptor.createPipe();
captureUri = blobProvider.create(masterSecret, new ParcelFileDescriptor.AutoCloseInputStream(fds[0]));
captureUri = blobProvider.create(masterSecret,
new ParcelFileDescriptor.AutoCloseInputStream(fds[0]),
ContentType.AUDIO_AAC);
audioCodec = new AudioCodec();
audioCodec.start(new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]));

View File

@ -159,7 +159,8 @@ public class AttachmentManager {
@Override
public void onSuccess(@NonNull Bitmap result) {
byte[] blob = BitmapUtil.toByteArray(result);
Uri uri = PersistentBlobProvider.getInstance(context).create(masterSecret, blob);
Uri uri = PersistentBlobProvider.getInstance(context)
.create(masterSecret, blob, ContentType.IMAGE_PNG);
LocationSlide locationSlide = new LocationSlide(context, uri, blob.length, place);
setSlide(locationSlide);
@ -273,7 +274,8 @@ public class AttachmentManager {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (captureIntent.resolveActivity(activity.getPackageManager()) != null) {
if (captureUri == null) {
captureUri = PersistentBlobProvider.getInstance(context).createForExternal();
captureUri = PersistentBlobProvider.getInstance(context)
.createForExternal(ContentType.IMAGE_JPEG);
}
Log.w(TAG, "captureUri path is " + captureUri.getPath());
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, captureUri);

View File

@ -1,16 +1,18 @@
package org.thoughtcrime.securesms.providers;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.webkit.MimeTypeMap;
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Util;
import java.io.ByteArrayInputStream;
@ -18,7 +20,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -29,12 +30,14 @@ public class PersistentBlobProvider {
private static final String TAG = PersistentBlobProvider.class.getSimpleName();
private static final String URI_STRING = "content://org.thoughtcrime.securesms/capture";
public static final Uri CONTENT_URI = Uri.parse(URI_STRING);
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String EXPECTED_PATH = "capture/*/#";
private static final int MATCH = 1;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH) {{
private static final String URI_STRING = "content://org.thoughtcrime.securesms/capture";
public static final Uri CONTENT_URI = Uri.parse(URI_STRING);
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String EXPECTED_PATH = "capture/*/*/#";
private static final int MIMETYPE_PATH_SEGMENT = 1;
private static final String BLOB_EXTENSION = "blob";
private static final int MATCH = 1;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH) {{
addURI(AUTHORITY, EXPECTED_PATH, MATCH);
}};
@ -51,7 +54,8 @@ public class PersistentBlobProvider {
return instance;
}
private final Context context;
private final Context context;
@SuppressLint("UseSparseArrays")
private final Map<Long, byte[]> cache = Collections.synchronizedMap(new HashMap<Long, byte[]>());
private final ExecutorService executor = Executors.newCachedThreadPool();
@ -60,22 +64,27 @@ public class PersistentBlobProvider {
}
public Uri create(@NonNull MasterSecret masterSecret,
@NonNull byte[] imageBytes)
@NonNull byte[] blobBytes,
@NonNull String mimeType)
{
final long id = System.currentTimeMillis();
cache.put(id, imageBytes);
return create(masterSecret, new ByteArrayInputStream(imageBytes), id);
cache.put(id, blobBytes);
return create(masterSecret, new ByteArrayInputStream(blobBytes), id, mimeType);
}
public Uri create(@NonNull MasterSecret masterSecret,
@NonNull InputStream input)
@NonNull InputStream input,
@NonNull String mimeType)
{
return create(masterSecret, input, System.currentTimeMillis());
return create(masterSecret, input, System.currentTimeMillis(), mimeType);
}
private Uri create(MasterSecret masterSecret, InputStream input, long id) {
private Uri create(MasterSecret masterSecret, InputStream input, long id, String mimeType) {
persistToDisk(masterSecret, id, input);
final Uri uniqueUri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(System.currentTimeMillis()));
final Uri uniqueUri = CONTENT_URI.buildUpon()
.appendPath(mimeType)
.appendEncodedPath(String.valueOf(System.currentTimeMillis()))
.build();
return ContentUris.withAppendedId(uniqueUri, id);
}
@ -97,10 +106,9 @@ public class PersistentBlobProvider {
});
}
public Uri createForExternal() throws IOException {
return Uri.fromFile(new File(getExternalDir(context), String.valueOf(System.currentTimeMillis()) + ".jpg"))
.buildUpon()
.build();
public Uri createForExternal(@NonNull String mimeType) throws IOException {
return Uri.fromFile(new File(getExternalDir(context),
String.valueOf(System.currentTimeMillis()) + "." + getExtensionFromMimeType(mimeType)));
}
public boolean delete(@NonNull Uri uri) {
@ -121,7 +129,17 @@ public class PersistentBlobProvider {
}
private File getFile(long id) {
return new File(context.getDir("captures", Context.MODE_PRIVATE), id + ".jpg");
return new File(context.getDir("captures", Context.MODE_PRIVATE), id + "." + BLOB_EXTENSION);
}
public static @Nullable String getMimeType(@NonNull Context context, @NonNull Uri persistentBlobUri) {
if (!isAuthority(context, persistentBlobUri)) return null;
return persistentBlobUri.getPathSegments().get(MIMETYPE_PATH_SEGMENT);
}
private static @NonNull String getExtensionFromMimeType(String mimeType) {
final String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
return extension != null ? extension : BLOB_EXTENSION;
}
private static @NonNull File getExternalDir(Context context) throws IOException {

View File

@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.mms.ImageSlide;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import java.io.IOException;
import java.io.InputStream;
@ -71,10 +72,14 @@ public class MediaUtil {
}
public static @Nullable String getMimeType(Context context, Uri uri) {
if (PersistentBlobProvider.isAuthority(context, uri)) {
return PersistentBlobProvider.getMimeType(context, uri);
}
String type = context.getContentResolver().getType(uri);
if (type == null) {
final String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
}
return getCorrectedMimeType(type);
}