diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java index efa1825653..57595ca620 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -69,7 +69,6 @@ import org.thoughtcrime.securesms.payments.preferences.model.PayeeParcelable; import org.signal.core.util.permissions.PermissionCompat; import org.signal.core.ui.permissions.Permissions; import org.thoughtcrime.securesms.providers.BlobProvider; -import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.sms.MessageSender; @@ -174,16 +173,14 @@ public class AttachmentManager { } private void cleanup(final @Nullable Uri uri) { - if (uri != null && DeprecatedPersistentBlobProvider.isAuthority(context, uri)) { + if (uri != null && BlobProvider.isAuthority(uri)) { Log.d(TAG, "cleaning up " + uri); - DeprecatedPersistentBlobProvider.getInstance(context).delete(context, uri); - } else if (uri != null && BlobProvider.isAuthority(uri)) { BlobProvider.getInstance().delete(context, uri); } } private void markGarbage(@Nullable Uri uri) { - if (uri != null && (DeprecatedPersistentBlobProvider.isAuthority(context, uri) || BlobProvider.isAuthority(uri))) { + if (uri != null && BlobProvider.isAuthority(uri)) { Log.d(TAG, "Marking garbage that needs cleaning: " + uri); garbage.add(uri); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java b/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java index 263bdae911..e12032a325 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java @@ -20,7 +20,6 @@ import org.signal.core.models.media.TransformProperties; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.emoji.EmojiFiles; import org.thoughtcrime.securesms.providers.BlobProvider; -import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider; import org.thoughtcrime.securesms.providers.PartProvider; import java.io.FileNotFoundException; @@ -42,7 +41,6 @@ public class PartAuthority { private static final Uri AVATAR_PICKER_CONTENT_URI = Uri.parse(AVATAR_PICKER_URI_STRING); private static final int PART_ROW = 1; - private static final int PERSISTENT_ROW = 2; private static final int BLOB_ROW = 3; private static final int STICKER_ROW = 4; private static final int WALLPAPER_ROW = 5; @@ -60,8 +58,6 @@ public class PartAuthority { uriMatcher.addURI(AUTHORITY, "wallpaper/*", WALLPAPER_ROW); uriMatcher.addURI(AUTHORITY, "emoji/*", EMOJI_ROW); uriMatcher.addURI(AUTHORITY, "avatar_picker/*", AVATAR_PICKER_ROW); - uriMatcher.addURI(DeprecatedPersistentBlobProvider.AUTHORITY, DeprecatedPersistentBlobProvider.EXPECTED_PATH_OLD, PERSISTENT_ROW); - uriMatcher.addURI(DeprecatedPersistentBlobProvider.AUTHORITY, DeprecatedPersistentBlobProvider.EXPECTED_PATH_NEW, PERSISTENT_ROW); uriMatcher.addURI(BlobProvider.AUTHORITY, BlobProvider.PATH, BLOB_ROW); } @@ -79,7 +75,6 @@ public class PartAuthority { switch (match) { case PART_ROW: return SignalDatabase.attachments().getAttachmentStream(new PartUriParser(uri).getPartId(), 0); case STICKER_ROW: return SignalDatabase.stickers().getStickerStream(ContentUris.parseId(uri)); - case PERSISTENT_ROW: return DeprecatedPersistentBlobProvider.getInstance(context).getStream(context, ContentUris.parseId(uri)); case BLOB_ROW: return BlobProvider.getInstance().getStream(context, uri); case EMOJI_ROW: return EmojiFiles.openForReading(context, getEmojiFilename(uri)); case AVATAR_PICKER_ROW: return AvatarPickerStorage.read(context, getAvatarPickerFilename(uri)); @@ -100,8 +95,6 @@ public class PartAuthority { if (attachment != null) return attachment.fileName; else return null; - case PERSISTENT_ROW: - return DeprecatedPersistentBlobProvider.getFileName(context, uri); case BLOB_ROW: return BlobProvider.getFileName(uri); default: @@ -118,8 +111,6 @@ public class PartAuthority { if (attachment != null) return attachment.size; else return null; - case PERSISTENT_ROW: - return DeprecatedPersistentBlobProvider.getFileSize(context, uri); case BLOB_ROW: return BlobProvider.getFileSize(uri); default: @@ -136,8 +127,6 @@ public class PartAuthority { if (attachment != null) return attachment.contentType; else return null; - case PERSISTENT_ROW: - return DeprecatedPersistentBlobProvider.getMimeType(context, uri); case BLOB_ROW: return BlobProvider.getMimeType(uri); default: @@ -211,7 +200,6 @@ public class PartAuthority { switch (match) { case PART_ROW: case THUMBNAIL_ROW: - case PERSISTENT_ROW: case BLOB_ROW: return true; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/providers/DeprecatedPersistentBlobProvider.java b/app/src/main/java/org/thoughtcrime/securesms/providers/DeprecatedPersistentBlobProvider.java deleted file mode 100644 index cca4314915..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/providers/DeprecatedPersistentBlobProvider.java +++ /dev/null @@ -1,195 +0,0 @@ -package org.thoughtcrime.securesms.providers; - -import android.content.ContentUris; -import android.content.Context; -import android.content.UriMatcher; -import android.net.Uri; -import android.webkit.MimeTypeMap; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.crypto.AttachmentSecret; -import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider; -import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; -import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; -import org.thoughtcrime.securesms.util.FileProviderUtil; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -/** - * @deprecated Use {@link BlobProvider} instead. Keeping in read-only mode due to the number of - * legacy URIs it handles. Given that this was largely used for drafts, and that files were stored - * in the cache directory, it's possible that we could remove this class after a reasonable amount - * of time has passed. - */ -@Deprecated -public class DeprecatedPersistentBlobProvider { - - private static final String TAG = Log.tag(DeprecatedPersistentBlobProvider.class); - - public static final String AUTHORITY = BuildConfig.APPLICATION_ID; - private static final String URI_STRING = "content://" + AUTHORITY + "/capture-new"; - public static final Uri CONTENT_URI = Uri.parse(URI_STRING); - public static final String EXPECTED_PATH_OLD = "capture/*/*/#"; - public static final String EXPECTED_PATH_NEW = "capture-new/*/*/*/*/#"; - - private static final int MIMETYPE_PATH_SEGMENT = 1; - private static final int FILENAME_PATH_SEGMENT = 2; - private static final int FILESIZE_PATH_SEGMENT = 3; - - private static final String BLOB_EXTENSION = "blob"; - private static final int MATCH_OLD = 1; - private static final int MATCH_NEW = 2; - - private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH) {{ - addURI(AUTHORITY, EXPECTED_PATH_OLD, MATCH_OLD); - addURI(AUTHORITY, EXPECTED_PATH_NEW, MATCH_NEW); - }}; - - private static volatile DeprecatedPersistentBlobProvider instance; - - /** - * @deprecated Use {@link BlobProvider} instead. - */ - @Deprecated - public static DeprecatedPersistentBlobProvider getInstance(Context context) { - if (instance == null) { - synchronized (DeprecatedPersistentBlobProvider.class) { - if (instance == null) { - instance = new DeprecatedPersistentBlobProvider(context); - } - } - } - return instance; - } - - private final AttachmentSecret attachmentSecret; - - private DeprecatedPersistentBlobProvider(@NonNull Context context) { - this.attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret(); - } - - public Uri createForExternal(@NonNull Context context, @NonNull String mimeType) throws IOException { - File target = new File(getExternalDir(context), String.valueOf(System.currentTimeMillis()) + "." + getExtensionFromMimeType(mimeType)); - return FileProviderUtil.getUriFor(context, target); - } - - public boolean delete(@NonNull Context context, @NonNull Uri uri) { - switch (MATCHER.match(uri)) { - case MATCH_OLD: - case MATCH_NEW: - long id = ContentUris.parseId(uri); - return getFile(context, ContentUris.parseId(uri)).file.delete(); - } - - //noinspection SimplifiableIfStatement - if (isExternalBlobUri(context, uri)) { - return FileProviderUtil.delete(context, uri); - } - - return false; - } - - public @NonNull InputStream getStream(@NonNull Context context, long id) throws IOException { - FileData fileData = getFile(context, id); - - if (fileData.modern) return ModernDecryptingPartInputStream.createFor(attachmentSecret, fileData.file, 0); - else return ClassicDecryptingPartInputStream.createFor(attachmentSecret, fileData.file); - } - - private FileData getFile(@NonNull Context context, long id) { - File legacy = getLegacyFile(context, id); - File cache = getCacheFile(context, id); - File modernCache = getModernCacheFile(context, id); - - if (legacy.exists()) return new FileData(legacy, false); - else if (cache.exists()) return new FileData(cache, false); - else return new FileData(modernCache, true); - } - - private File getLegacyFile(@NonNull Context context, long id) { - return new File(context.getDir("captures", Context.MODE_PRIVATE), id + "." + BLOB_EXTENSION); - } - - private File getCacheFile(@NonNull Context context, long id) { - return new File(context.getCacheDir(), "capture-" + id + "." + BLOB_EXTENSION); - } - - private File getModernCacheFile(@NonNull Context context, long id) { - return new File(context.getCacheDir(), "capture-m-" + id + "." + BLOB_EXTENSION); - } - - public static @Nullable String getMimeType(@NonNull Context context, @NonNull Uri persistentBlobUri) { - if (!isAuthority(context, persistentBlobUri)) return null; - return isExternalBlobUri(context, persistentBlobUri) - ? getMimeTypeFromExtension(persistentBlobUri) - : persistentBlobUri.getPathSegments().get(MIMETYPE_PATH_SEGMENT); - } - - public static @Nullable String getFileName(@NonNull Context context, @NonNull Uri persistentBlobUri) { - if (!isAuthority(context, persistentBlobUri)) return null; - if (isExternalBlobUri(context, persistentBlobUri)) return null; - if (MATCHER.match(persistentBlobUri) == MATCH_OLD) return null; - - return persistentBlobUri.getPathSegments().get(FILENAME_PATH_SEGMENT); - } - - public static @Nullable Long getFileSize(@NonNull Context context, Uri persistentBlobUri) { - if (!isAuthority(context, persistentBlobUri)) return null; - if (isExternalBlobUri(context, persistentBlobUri)) return null; - if (MATCHER.match(persistentBlobUri) == MATCH_OLD) return null; - - try { - return Long.valueOf(persistentBlobUri.getPathSegments().get(FILESIZE_PATH_SEGMENT)); - } catch (NumberFormatException e) { - Log.w(TAG, e); - return null; - } - } - - private static @NonNull String getExtensionFromMimeType(String mimeType) { - final String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType); - return extension != null ? extension : BLOB_EXTENSION; - } - - private static @NonNull String getMimeTypeFromExtension(@NonNull Uri uri) { - final String mimeType = MimeTypeMap.getSingleton() - .getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(uri.toString())); - return mimeType != null ? mimeType : "application/octet-stream"; - } - - private static @NonNull File getExternalDir(Context context) throws IOException { - final File externalDir = context.getExternalCacheDir(); - if (externalDir == null) throw new IOException("no external files directory"); - return externalDir; - } - - public static boolean isAuthority(@NonNull Context context, @NonNull Uri uri) { - int matchResult = MATCHER.match(uri); - return matchResult == MATCH_NEW || matchResult == MATCH_OLD || isExternalBlobUri(context, uri); - } - - private static boolean isExternalBlobUri(@NonNull Context context, @NonNull Uri uri) { - try { - return uri.getPath().startsWith(getExternalDir(context).getAbsolutePath()) || FileProviderUtil.isAuthority(uri); - } catch (IOException ioe) { - Log.w(TAG, "Failed to determine if it's an external blob URI.", ioe); - return false; - } - } - - private static class FileData { - private final File file; - private final boolean modern; - - private FileData(File file, boolean modern) { - this.file = file; - this.modern = modern; - } - } -}