Search in sources :

Example 46 with MmsException

use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.

the class AttachmentCompressionJob method transcodeVideoIfNeededToDatabase.

@NonNull
private static DatabaseAttachment transcodeVideoIfNeededToDatabase(@NonNull Context context, @NonNull AttachmentDatabase attachmentDatabase, @NonNull DatabaseAttachment attachment, @NonNull MediaConstraints constraints, @NonNull EventBus eventBus, @NonNull TranscoderCancelationSignal cancelationSignal) throws UndeliverableMessageException {
    AttachmentDatabase.TransformProperties transformProperties = attachment.getTransformProperties();
    boolean allowSkipOnFailure = false;
    if (!MediaConstraints.isVideoTranscodeAvailable()) {
        if (transformProperties.isVideoEdited()) {
            throw new UndeliverableMessageException("Video edited, but transcode is not available");
        }
        return attachment;
    }
    try (NotificationController notification = GenericForegroundService.startForegroundTask(context, context.getString(R.string.AttachmentUploadJob_compressing_video_start))) {
        notification.setIndeterminateProgress();
        try (MediaDataSource dataSource = attachmentDatabase.mediaDataSourceFor(attachment.getAttachmentId())) {
            if (dataSource == null) {
                throw new UndeliverableMessageException("Cannot get media data source for attachment.");
            }
            allowSkipOnFailure = !transformProperties.isVideoEdited();
            TranscoderOptions options = null;
            if (transformProperties.isVideoTrim()) {
                options = new TranscoderOptions(transformProperties.getVideoTrimStartTimeUs(), transformProperties.getVideoTrimEndTimeUs());
            }
            if (FeatureFlags.useStreamingVideoMuxer() || !MemoryFileDescriptor.supported()) {
                StreamingTranscoder transcoder = new StreamingTranscoder(dataSource, options, constraints.getCompressedVideoMaxSize(context));
                if (transcoder.isTranscodeRequired()) {
                    Log.i(TAG, "Compressing with streaming muxer");
                    AttachmentSecret attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret();
                    File file = SignalDatabase.attachments().newFile();
                    file.deleteOnExit();
                    try {
                        try (OutputStream outputStream = ModernEncryptingPartOutputStream.createFor(attachmentSecret, file, true).second) {
                            transcoder.transcode(percent -> {
                                notification.setProgress(100, percent);
                                eventBus.postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.COMPRESSION, 100, percent));
                            }, outputStream, cancelationSignal);
                        }
                        MediaStream mediaStream = new MediaStream(ModernDecryptingPartInputStream.createFor(attachmentSecret, file, 0), MimeTypes.VIDEO_MP4, 0, 0);
                        attachmentDatabase.updateAttachmentData(attachment, mediaStream, transformProperties.isVideoEdited());
                    } finally {
                        if (!file.delete()) {
                            Log.w(TAG, "Failed to delete temp file");
                        }
                    }
                    attachmentDatabase.markAttachmentAsTransformed(attachment.getAttachmentId());
                    return Objects.requireNonNull(attachmentDatabase.getAttachment(attachment.getAttachmentId()));
                } else {
                    Log.i(TAG, "Transcode was not required");
                }
            } else {
                try (InMemoryTranscoder transcoder = new InMemoryTranscoder(context, dataSource, options, constraints.getCompressedVideoMaxSize(context))) {
                    if (transcoder.isTranscodeRequired()) {
                        Log.i(TAG, "Compressing with android in-memory muxer");
                        MediaStream mediaStream = transcoder.transcode(percent -> {
                            notification.setProgress(100, percent);
                            eventBus.postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.COMPRESSION, 100, percent));
                        }, cancelationSignal);
                        attachmentDatabase.updateAttachmentData(attachment, mediaStream, transformProperties.isVideoEdited());
                        attachmentDatabase.markAttachmentAsTransformed(attachment.getAttachmentId());
                        return Objects.requireNonNull(attachmentDatabase.getAttachment(attachment.getAttachmentId()));
                    } else {
                        Log.i(TAG, "Transcode was not required (in-memory transcoder)");
                    }
                }
            }
        }
    } catch (VideoSourceException | EncodingException | MemoryFileException e) {
        if (attachment.getSize() > constraints.getVideoMaxSize(context)) {
            throw new UndeliverableMessageException("Duration not found, attachment too large to skip transcode", e);
        } else {
            if (allowSkipOnFailure) {
                Log.w(TAG, "Problem with video source, but video small enough to skip transcode", e);
            } else {
                throw new UndeliverableMessageException("Failed to transcode and cannot skip due to editing", e);
            }
        }
    } catch (IOException | MmsException e) {
        throw new UndeliverableMessageException("Failed to transcode", e);
    }
    return attachment;
}
Also used : VideoSourceException(org.thoughtcrime.securesms.video.VideoSourceException) MemoryFileException(org.thoughtcrime.securesms.util.MemoryFileDescriptor.MemoryFileException) EncodingException(org.thoughtcrime.securesms.video.videoconverter.EncodingException) OutputStream(java.io.OutputStream) ModernEncryptingPartOutputStream(org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream) PartProgressEvent(org.thoughtcrime.securesms.events.PartProgressEvent) IOException(java.io.IOException) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) TranscoderOptions(org.thoughtcrime.securesms.video.TranscoderOptions) MmsException(org.thoughtcrime.securesms.mms.MmsException) InMemoryTranscoder(org.thoughtcrime.securesms.video.InMemoryTranscoder) MediaStream(org.thoughtcrime.securesms.mms.MediaStream) MediaDataSource(android.media.MediaDataSource) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) StreamingTranscoder(org.thoughtcrime.securesms.video.StreamingTranscoder) AttachmentSecret(org.thoughtcrime.securesms.crypto.AttachmentSecret) File(java.io.File) NotificationController(org.thoughtcrime.securesms.service.NotificationController) NonNull(androidx.annotation.NonNull)

Example 47 with MmsException

use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.

the class MessageContentProcessor method handleExpirationUpdate.

@Nullable
private MessageId handleExpirationUpdate(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Optional<Long> smsMessageId, @NonNull Optional<GroupId> groupId, @NonNull Recipient senderRecipient, @NonNull Recipient threadRecipient, long receivedTime) throws StorageFailedException {
    log(content.getTimestamp(), "Expiration update.");
    if (groupId.isPresent() && groupId.get().isV2()) {
        warn(String.valueOf(content.getTimestamp()), "Expiration update received for GV2. Ignoring.");
        return null;
    }
    int expiresInSeconds = message.getExpiresInSeconds();
    Optional<SignalServiceGroupContext> groupContext = message.getGroupContext();
    if (threadRecipient.getExpiresInSeconds() == expiresInSeconds) {
        log(String.valueOf(content.getTimestamp()), "No change in message expiry for group. Ignoring.");
        return null;
    }
    try {
        MessageDatabase database = SignalDatabase.mms();
        IncomingMediaMessage mediaMessage = new IncomingMediaMessage(senderRecipient.getId(), content.getTimestamp(), content.getServerReceivedTimestamp(), receivedTime, -1, expiresInSeconds * 1000L, true, false, content.isNeedsReceipt(), Optional.absent(), groupContext, Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), content.getServerUuid());
        Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
        SignalDatabase.recipients().setExpireMessages(threadRecipient.getId(), expiresInSeconds);
        if (smsMessageId.isPresent()) {
            SignalDatabase.sms().deleteMessage(smsMessageId.get());
        }
        if (insertResult.isPresent()) {
            return new MessageId(insertResult.get().getMessageId(), true);
        }
    } catch (MmsException e) {
        throw new StorageFailedException(e, content.getSender().getIdentifier(), content.getSenderDevice());
    }
    return null;
}
Also used : InsertResult(org.thoughtcrime.securesms.database.MessageDatabase.InsertResult) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) MmsException(org.thoughtcrime.securesms.mms.MmsException) IncomingMediaMessage(org.thoughtcrime.securesms.mms.IncomingMediaMessage) SuppressLint(android.annotation.SuppressLint) SignalServiceGroupContext(org.whispersystems.signalservice.api.messages.SignalServiceGroupContext) MessageId(org.thoughtcrime.securesms.database.model.MessageId) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId) Nullable(androidx.annotation.Nullable)

Example 48 with MmsException

use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by WhisperSystems.

the class AttachmentDatabase method insertAttachmentForPreUpload.

@NonNull
public DatabaseAttachment insertAttachmentForPreUpload(@NonNull Attachment attachment) throws MmsException {
    Map<Attachment, AttachmentId> result = insertAttachmentsForMessage(PREUPLOAD_MESSAGE_ID, Collections.singletonList(attachment), Collections.emptyList());
    if (result.values().isEmpty()) {
        throw new MmsException("Bad attachment result!");
    }
    DatabaseAttachment databaseAttachment = getAttachment(result.values().iterator().next());
    if (databaseAttachment == null) {
        throw new MmsException("Failed to retrieve attachment we just inserted!");
    }
    return databaseAttachment;
}
Also used : MmsException(org.thoughtcrime.securesms.mms.MmsException) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) NonNull(androidx.annotation.NonNull)

Example 49 with MmsException

use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by signalapp.

the class MmsDatabase method getOutgoingMessage.

@Override
public OutgoingMediaMessage getOutgoingMessage(long messageId) throws MmsException, NoSuchMessageException {
    AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
    MentionDatabase mentionDatabase = SignalDatabase.mentions();
    Cursor cursor = null;
    try {
        cursor = rawQuery(RAW_ID_WHERE, new String[] { String.valueOf(messageId) });
        if (cursor != null && cursor.moveToNext()) {
            List<DatabaseAttachment> associatedAttachments = attachmentDatabase.getAttachmentsForMessage(messageId);
            List<Mention> mentions = mentionDatabase.getMentionsForMessage(messageId);
            long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
            String body = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
            long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
            int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
            long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
            boolean viewOnce = cursor.getLong(cursor.getColumnIndexOrThrow(VIEW_ONCE)) == 1;
            long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT_ID));
            long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
            int distributionType = SignalDatabase.threads().getDistributionType(threadId);
            String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
            String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
            long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID));
            long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR));
            String quoteText = cursor.getString(cursor.getColumnIndexOrThrow(QUOTE_BODY));
            boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(QUOTE_MISSING)) == 1;
            List<Attachment> quoteAttachments = Stream.of(associatedAttachments).filter(Attachment::isQuote).map(a -> (Attachment) a).toList();
            List<Mention> quoteMentions = parseQuoteMentions(context, cursor);
            List<Contact> contacts = getSharedContacts(cursor, associatedAttachments);
            Set<Attachment> contactAttachments = new HashSet<>(Stream.of(contacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList());
            List<LinkPreview> previews = getLinkPreviews(cursor, associatedAttachments);
            Set<Attachment> previewAttachments = Stream.of(previews).filter(lp -> lp.getThumbnail().isPresent()).map(lp -> lp.getThumbnail().get()).collect(Collectors.toSet());
            List<Attachment> attachments = Stream.of(associatedAttachments).filterNot(Attachment::isQuote).filterNot(contactAttachments::contains).filterNot(previewAttachments::contains).sorted(new DatabaseAttachment.DisplayOrderComparator()).map(a -> (Attachment) a).toList();
            Recipient recipient = Recipient.resolved(RecipientId.from(recipientId));
            Set<NetworkFailure> networkFailures = new HashSet<>();
            Set<IdentityKeyMismatch> mismatches = new HashSet<>();
            QuoteModel quote = null;
            if (quoteId > 0 && quoteAuthor > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
                quote = new QuoteModel(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteAttachments, quoteMentions);
            }
            if (!TextUtils.isEmpty(mismatchDocument)) {
                try {
                    mismatches = JsonUtils.fromJson(mismatchDocument, IdentityKeyMismatchSet.class).getItems();
                } catch (IOException e) {
                    Log.w(TAG, e);
                }
            }
            if (!TextUtils.isEmpty(networkDocument)) {
                try {
                    networkFailures = JsonUtils.fromJson(networkDocument, NetworkFailureSet.class).getItems();
                } catch (IOException e) {
                    Log.w(TAG, e);
                }
            }
            if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
                return new OutgoingGroupUpdateMessage(recipient, new MessageGroupContext(body, Types.isGroupV2(outboxType)), attachments, timestamp, 0, false, quote, contacts, previews, mentions);
            } else if (Types.isExpirationTimerUpdate(outboxType)) {
                return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
            }
            OutgoingMediaMessage message = new OutgoingMediaMessage(recipient, body, attachments, timestamp, subscriptionId, expiresIn, viewOnce, distributionType, quote, contacts, previews, mentions, networkFailures, mismatches);
            if (Types.isSecureType(outboxType)) {
                return new OutgoingSecureMediaMessage(message);
            }
            return message;
        }
        throw new NoSuchMessageException("No record found for id: " + messageId);
    } catch (IOException e) {
        throw new MmsException(e);
    } finally {
        if (cursor != null)
            cursor.close();
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) SlideDeck(org.thoughtcrime.securesms.mms.SlideDeck) GroupMigrationMembershipChange(org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) NonNull(androidx.annotation.NonNull) Avatar(org.thoughtcrime.securesms.contactshare.Contact.Avatar) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) Mention(org.thoughtcrime.securesms.database.model.Mention) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) SecureRandom(java.security.SecureRandom) JSONException(org.json.JSONException) JsonUtils(org.thoughtcrime.securesms.util.JsonUtils) JSONObject(org.json.JSONObject) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) BodyRangeList(org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList) SqlUtil(org.thoughtcrime.securesms.util.SqlUtil) IdentityKeyMismatchSet(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet) Map(java.util.Map) ViewOnceUtil(org.thoughtcrime.securesms.revealable.ViewOnceUtil) Recipient(org.thoughtcrime.securesms.recipients.Recipient) OutgoingTextMessage(org.thoughtcrime.securesms.sms.OutgoingTextMessage) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) NotificationInd(com.google.android.mms.pdu_alt.NotificationInd) ACI(org.whispersystems.signalservice.api.push.ACI) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) Set(java.util.Set) UUID(java.util.UUID) OutgoingExpirationUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage) Log(org.signal.core.util.logging.Log) NetworkFailureSet(org.thoughtcrime.securesms.database.documents.NetworkFailureSet) List(java.util.List) Nullable(androidx.annotation.Nullable) ContentValues(android.content.ContentValues) IncomingTextMessage(org.thoughtcrime.securesms.sms.IncomingTextMessage) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) MediaUtil(org.thoughtcrime.securesms.util.MediaUtil) Context(android.content.Context) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) HashMap(java.util.HashMap) SQLiteStatement(net.zetetic.database.sqlcipher.SQLiteStatement) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) ArrayList(java.util.ArrayList) TextSecurePreferences(org.thoughtcrime.securesms.util.TextSecurePreferences) HashSet(java.util.HashSet) Pair(org.whispersystems.libsignal.util.Pair) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) NotificationMmsMessageRecord(org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord) QuoteModel(org.thoughtcrime.securesms.mms.QuoteModel) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) LinkedList(java.util.LinkedList) PduHeaders(com.google.android.mms.pdu_alt.PduHeaders) Cursor(android.database.Cursor) MessageId(org.thoughtcrime.securesms.database.model.MessageId) Collectors(com.annimon.stream.Collectors) Contact(org.thoughtcrime.securesms.contactshare.Contact) IdentityKeyMismatch(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch) MmsException(org.thoughtcrime.securesms.mms.MmsException) TextUtils(android.text.TextUtils) IOException(java.io.IOException) Quote(org.thoughtcrime.securesms.database.model.Quote) Optional(org.whispersystems.libsignal.util.guava.Optional) CursorUtil(org.thoughtcrime.securesms.util.CursorUtil) ViewOnceExpirationInfo(org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) NetworkFailure(org.thoughtcrime.securesms.database.documents.NetworkFailure) TrimThreadJob(org.thoughtcrime.securesms.jobs.TrimThreadJob) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) Collections(java.util.Collections) JSONArray(org.json.JSONArray) IncomingMediaMessage(org.thoughtcrime.securesms.mms.IncomingMediaMessage) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) Attachment(org.thoughtcrime.securesms.attachments.Attachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) Cursor(android.database.Cursor) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) MmsException(org.thoughtcrime.securesms.mms.MmsException) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) Mention(org.thoughtcrime.securesms.database.model.Mention) HashSet(java.util.HashSet) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) Recipient(org.thoughtcrime.securesms.recipients.Recipient) NetworkFailure(org.thoughtcrime.securesms.database.documents.NetworkFailure) IdentityKeyMismatch(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch) IOException(java.io.IOException) QuoteModel(org.thoughtcrime.securesms.mms.QuoteModel) Contact(org.thoughtcrime.securesms.contactshare.Contact) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) OutgoingExpirationUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage)

Example 50 with MmsException

use of org.thoughtcrime.securesms.mms.MmsException in project Signal-Android by signalapp.

the class MessageContentProcessor method handleSynchronizeSentMessage.

private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content, @NonNull SentTranscriptMessage message, @NonNull Recipient senderRecipient) throws StorageFailedException, BadGroupIdException, IOException, GroupChangeBusyException {
    log(String.valueOf(content.getTimestamp()), "Processing sent transcript for message with ID " + message.getTimestamp());
    try {
        GroupDatabase groupDatabase = SignalDatabase.groups();
        if (message.getMessage().isGroupV2Message()) {
            GroupId.V2 groupId = GroupId.v2(message.getMessage().getGroupContext().get().getGroupV2().get().getMasterKey());
            if (handleGv2PreProcessing(groupId, content, message.getMessage().getGroupContext().get().getGroupV2().get(), senderRecipient)) {
                return;
            }
        }
        long threadId = -1;
        if (message.isRecipientUpdate()) {
            handleGroupRecipientUpdate(message, content.getTimestamp());
        } else if (message.getMessage().isEndSession()) {
            threadId = handleSynchronizeSentEndSessionMessage(message, content.getTimestamp());
        } else if (message.getMessage().isGroupV1Update()) {
            Long gv1ThreadId = GroupV1MessageProcessor.process(context, content, message.getMessage(), true);
            threadId = gv1ThreadId == null ? -1 : gv1ThreadId;
        } else if (message.getMessage().isGroupV2Update()) {
            handleSynchronizeSentGv2Update(content, message);
            threadId = SignalDatabase.threads().getOrCreateThreadIdFor(getSyncMessageDestination(message));
        } else if (Build.VERSION.SDK_INT > 19 && message.getMessage().getGroupCallUpdate().isPresent()) {
            handleGroupCallUpdateMessage(content, message.getMessage(), GroupUtil.idFromGroupContext(message.getMessage().getGroupContext()), senderRecipient);
        } else if (message.getMessage().isEmptyGroupV2Message()) {
            warn(content.getTimestamp(), "Empty GV2 message! Doing nothing.");
        } else if (message.getMessage().isExpirationUpdate()) {
            threadId = handleSynchronizeSentExpirationUpdate(message);
        } else if (message.getMessage().getReaction().isPresent()) {
            handleReaction(content, message.getMessage(), senderRecipient);
            threadId = SignalDatabase.threads().getOrCreateThreadIdFor(getSyncMessageDestination(message));
        } else if (message.getMessage().getRemoteDelete().isPresent()) {
            handleRemoteDelete(content, message.getMessage(), senderRecipient);
        } else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent() || message.getMessage().isViewOnce() || message.getMessage().getMentions().isPresent()) {
            threadId = handleSynchronizeSentMediaMessage(message, content.getTimestamp());
        } else {
            threadId = handleSynchronizeSentTextMessage(message, content.getTimestamp());
        }
        if (message.getMessage().getGroupContext().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.idFromGroupContext(message.getMessage().getGroupContext().get()))) {
            handleUnknownGroupMessage(content, message.getMessage().getGroupContext().get(), senderRecipient);
        }
        if (message.getMessage().getProfileKey().isPresent()) {
            Recipient recipient = getSyncMessageDestination(message);
            if (recipient != null && !recipient.isSystemContact() && !recipient.isProfileSharing()) {
                SignalDatabase.recipients().setProfileSharing(recipient.getId(), true);
            }
        }
        if (threadId != -1) {
            SignalDatabase.threads().setRead(threadId, true);
            ApplicationDependencies.getMessageNotifier().updateNotification(context);
        }
        if (SignalStore.rateLimit().needsRecaptcha()) {
            log(content.getTimestamp(), "Got a sent transcript while in reCAPTCHA mode. Assuming we're good to message again.");
            RateLimitUtil.retryAllRateLimitedMessages(context);
        }
        ApplicationDependencies.getMessageNotifier().setLastDesktopActivityTimestamp(message.getTimestamp());
    } catch (MmsException e) {
        throw new StorageFailedException(e, content.getSender().getIdentifier(), content.getSenderDevice());
    }
}
Also used : MmsException(org.thoughtcrime.securesms.mms.MmsException) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) Recipient(org.thoughtcrime.securesms.recipients.Recipient) GroupId(org.thoughtcrime.securesms.groups.GroupId)

Aggregations

MmsException (org.thoughtcrime.securesms.mms.MmsException)61 IOException (java.io.IOException)26 Recipient (org.thoughtcrime.securesms.recipients.Recipient)26 MessageDatabase (org.thoughtcrime.securesms.database.MessageDatabase)24 NonNull (androidx.annotation.NonNull)20 DatabaseAttachment (org.thoughtcrime.securesms.attachments.DatabaseAttachment)20 OutgoingMediaMessage (org.thoughtcrime.securesms.mms.OutgoingMediaMessage)19 Nullable (androidx.annotation.Nullable)18 Attachment (org.thoughtcrime.securesms.attachments.Attachment)18 AttachmentDatabase (org.thoughtcrime.securesms.database.AttachmentDatabase)15 List (java.util.List)14 MessageId (org.thoughtcrime.securesms.database.model.MessageId)14 Context (android.content.Context)12 WorkerThread (androidx.annotation.WorkerThread)12 Stream (com.annimon.stream.Stream)12 LinkedList (java.util.LinkedList)12 Log (org.signal.core.util.logging.Log)12 AttachmentId (org.thoughtcrime.securesms.attachments.AttachmentId)12 NoSuchMessageException (org.thoughtcrime.securesms.database.NoSuchMessageException)12 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)12