Fix NPE when link preview image cannot be decoded.

master
Alan Evans 2020-08-15 10:10:15 -03:00
parent 4b7efbfdc0
commit 57e0e57f48
1 changed files with 43 additions and 57 deletions

View File

@ -4,9 +4,9 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import android.text.Html; import androidx.annotation.Nullable;
import android.text.TextUtils;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.net.CallRequestController; import org.thoughtcrime.securesms.net.CallRequestController;
import org.thoughtcrime.securesms.net.CompositeRequestController; import org.thoughtcrime.securesms.net.CompositeRequestController;
import org.thoughtcrime.securesms.net.ContentProxySafetyInterceptor;
import org.thoughtcrime.securesms.net.RequestController; import org.thoughtcrime.securesms.net.RequestController;
import org.thoughtcrime.securesms.net.UserAgentInterceptor; import org.thoughtcrime.securesms.net.UserAgentInterceptor;
import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.BlobProvider;
@ -36,14 +35,11 @@ import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifest; import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifest;
import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifest.StickerInfo; import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifest.StickerInfo;
import org.whispersystems.signalservice.api.util.OptionalUtil;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.CacheControl; import okhttp3.CacheControl;
import okhttp3.Call; import okhttp3.Call;
@ -163,31 +159,9 @@ public class LinkPreviewRepository {
InputStream bodyStream = response.body().byteStream(); InputStream bodyStream = response.body().byteStream();
controller.setStream(bodyStream); controller.setStream(bodyStream);
byte[] data = OkHttpUtil.readAsBytes(bodyStream, FAILSAFE_MAX_IMAGE_SIZE); byte[] data = OkHttpUtil.readAsBytes(bodyStream, FAILSAFE_MAX_IMAGE_SIZE);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Optional<Attachment> thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.JPEG, MediaUtil.IMAGE_JPEG);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] bytes = baos.toByteArray();
Uri uri = BlobProvider.getInstance().forData(bytes).createForSingleSessionInMemory();
Optional<Attachment> thumbnail = Optional.of(new UriAttachment(uri,
uri,
MediaUtil.IMAGE_JPEG,
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
bytes.length,
bitmap.getWidth(),
bitmap.getHeight(),
null,
null,
false,
false,
false,
null,
null,
null,
null,
null));
callback.onComplete(thumbnail); callback.onComplete(thumbnail);
} catch (IOException e) { } catch (IOException e) {
@ -200,9 +174,9 @@ public class LinkPreviewRepository {
return controller; return controller;
} }
private RequestController fetchStickerPackLinkPreview(@NonNull Context context, private static RequestController fetchStickerPackLinkPreview(@NonNull Context context,
@NonNull String packUrl, @NonNull String packUrl,
@NonNull Callback<Optional<LinkPreview>> callback) @NonNull Callback<Optional<LinkPreview>> callback)
{ {
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
@ -228,29 +202,7 @@ public class LinkPreviewRepository {
.submit(512, 512) .submit(512, 512)
.get(); .get();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Optional<Attachment> thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP);
bitmap.compress(Bitmap.CompressFormat.WEBP, 80, baos);
byte[] bytes = baos.toByteArray();
Uri uri = BlobProvider.getInstance().forData(bytes).createForSingleSessionInMemory();
Optional<Attachment> thumbnail = Optional.of(new UriAttachment(uri,
uri,
MediaUtil.IMAGE_WEBP,
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
bytes.length,
bitmap.getWidth(),
bitmap.getHeight(),
null,
null,
false,
false,
false,
null,
null,
null,
null,
null));
callback.onComplete(Optional.of(new LinkPreview(packUrl, title, thumbnail))); callback.onComplete(Optional.of(new LinkPreview(packUrl, title, thumbnail)));
} else { } else {
@ -265,6 +217,40 @@ public class LinkPreviewRepository {
return () -> Log.i(TAG, "Cancelled sticker pack link preview fetch -- no effect."); return () -> Log.i(TAG, "Cancelled sticker pack link preview fetch -- no effect.");
} }
private static Optional<Attachment> bitmapToAttachment(@Nullable Bitmap bitmap,
@NonNull Bitmap.CompressFormat format,
@NonNull String contentType)
{
if (bitmap == null) {
return Optional.absent();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(format, 80, baos);
byte[] bytes = baos.toByteArray();
Uri uri = BlobProvider.getInstance().forData(bytes).createForSingleSessionInMemory();
return Optional.of(new UriAttachment(uri,
uri,
contentType,
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
bytes.length,
bitmap.getWidth(),
bitmap.getHeight(),
null,
null,
false,
false,
false,
null,
null,
null,
null,
null));
}
private static class Metadata { private static class Metadata {
private final Optional<String> title; private final Optional<String> title;
private final Optional<String> imageUrl; private final Optional<String> imageUrl;