Search in sources :

Example 11 with Job

use of org.thoughtcrime.securesms.jobmanager.Job in project Signal-Android by WhisperSystems.

the class PushDecryptMessageJob method onRun.

@Override
public void onRun() throws RetryLaterException {
    if (needsMigration()) {
        Log.w(TAG, "Migration is still needed.");
        postMigrationNotification();
        throw new RetryLaterException();
    }
    List<Job> jobs = new LinkedList<>();
    DecryptionResult result = MessageDecryptionUtil.decrypt(context, envelope);
    if (result.getContent() != null) {
        if (result.getContent().getSenderKeyDistributionMessage().isPresent()) {
            handleSenderKeyDistributionMessage(result.getContent().getSender(), result.getContent().getSenderDevice(), result.getContent().getSenderKeyDistributionMessage().get());
        }
        jobs.add(new PushProcessMessageJob(result.getContent(), smsMessageId, envelope.getTimestamp()));
    } else if (result.getException() != null && result.getState() != MessageState.NOOP) {
        jobs.add(new PushProcessMessageJob(result.getState(), result.getException(), smsMessageId, envelope.getTimestamp()));
    }
    jobs.addAll(result.getJobs());
    for (Job job : jobs) {
        ApplicationDependencies.getJobManager().add(job);
    }
}
Also used : DecryptionResult(org.thoughtcrime.securesms.messages.MessageDecryptionUtil.DecryptionResult) RetryLaterException(org.thoughtcrime.securesms.transport.RetryLaterException) Job(org.thoughtcrime.securesms.jobmanager.Job) LinkedList(java.util.LinkedList)

Example 12 with Job

use of org.thoughtcrime.securesms.jobmanager.Job in project Signal-Android by WhisperSystems.

the class MmsSendJob method enqueue.

/**
 * Enqueues compression jobs for attachments and finally the MMS send job.
 */
@WorkerThread
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId) {
    MessageDatabase database = SignalDatabase.mms();
    OutgoingMediaMessage message;
    try {
        message = database.getOutgoingMessage(messageId);
    } catch (MmsException | NoSuchMessageException e) {
        throw new AssertionError(e);
    }
    List<Job> compressionJobs = Stream.of(message.getAttachments()).map(a -> (Job) AttachmentCompressionJob.fromAttachment((DatabaseAttachment) a, true, message.getSubscriptionId())).toList();
    MmsSendJob sendJob = new MmsSendJob(messageId);
    jobManager.startChain(compressionJobs).then(sendJob).enqueue();
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) NumberUtil(org.thoughtcrime.securesms.phonenumbers.NumberUtil) Arrays(java.util.Arrays) NonNull(androidx.annotation.NonNull) Data(org.thoughtcrime.securesms.jobmanager.Data) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) PduPart(com.google.android.mms.pdu_alt.PduPart) InsecureFallbackApprovalException(org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException) Utils(com.klinker.android.send_message.Utils) SecureRandom(java.security.SecureRandom) SmilXmlSerializer(com.android.mms.dom.smil.parser.SmilXmlSerializer) Recipient(org.thoughtcrime.securesms.recipients.Recipient) PartAuthority(org.thoughtcrime.securesms.mms.PartAuthority) SendReq(com.google.android.mms.pdu_alt.SendReq) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) Log(org.signal.core.util.logging.Log) List(java.util.List) ContentType(com.google.android.mms.ContentType) SmilHelper(com.google.android.mms.smil.SmilHelper) Job(org.thoughtcrime.securesms.jobmanager.Job) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) NoSuchMessageException(org.thoughtcrime.securesms.database.NoSuchMessageException) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) Context(android.content.Context) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) Stream(com.annimon.stream.Stream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Util(org.thoughtcrime.securesms.util.Util) JobLogger(org.thoughtcrime.securesms.jobmanager.JobLogger) WorkerThread(androidx.annotation.WorkerThread) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) InvalidHeaderValueException(com.google.android.mms.InvalidHeaderValueException) PduHeaders(com.google.android.mms.pdu_alt.PduHeaders) StreamUtil(org.signal.core.util.StreamUtil) MmsException(org.thoughtcrime.securesms.mms.MmsException) EncodedStringValue(com.google.android.mms.pdu_alt.EncodedStringValue) TextUtils(android.text.TextUtils) NetworkConstraint(org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint) Hex(org.thoughtcrime.securesms.util.Hex) IOException(java.io.IOException) SendConf(com.google.android.mms.pdu_alt.SendConf) MediaConstraints(org.thoughtcrime.securesms.mms.MediaConstraints) CharacterSets(com.google.android.mms.pdu_alt.CharacterSets) PduComposer(com.google.android.mms.pdu_alt.PduComposer) CompatMmsConnection(org.thoughtcrime.securesms.mms.CompatMmsConnection) MmsSendResult(org.thoughtcrime.securesms.mms.MmsSendResult) MimeTypeMap(android.webkit.MimeTypeMap) PduBody(com.google.android.mms.pdu_alt.PduBody) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) MmsException(org.thoughtcrime.securesms.mms.MmsException) NoSuchMessageException(org.thoughtcrime.securesms.database.NoSuchMessageException) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) Job(org.thoughtcrime.securesms.jobmanager.Job) WorkerThread(androidx.annotation.WorkerThread)

Example 13 with Job

use of org.thoughtcrime.securesms.jobmanager.Job in project Signal-Android by WhisperSystems.

the class MarkReadReceiverTest method givenMultipleThreadsWithMultipleMessagesEach_whenIProcess_thenIProperlyGroupByThreadAndRecipient.

@Test
public void givenMultipleThreadsWithMultipleMessagesEach_whenIProcess_thenIProperlyGroupByThreadAndRecipient() {
    // GIVEN
    List<RecipientId> recipients = Stream.range(1L, 4L).map(RecipientId::from).toList();
    List<Long> threads = Stream.range(4L, 7L).toList();
    int expected = recipients.size() * threads.size() + 1;
    List<MessageDatabase.MarkedMessageInfo> infoList = Stream.of(threads).flatMap(threadId -> Stream.of(recipients).map(recipientId -> createMarkedMessageInfo(threadId, recipientId))).toList();
    List<MessageDatabase.MarkedMessageInfo> duplicatedList = Util.concatenatedList(infoList, infoList);
    // WHEN
    MarkReadReceiver.process(mockContext, duplicatedList);
    // THEN
    assertEquals("Should have 10 total jobs, including MultiDeviceReadUpdateJob", expected, jobs.size());
    Set<Pair<Long, String>> threadRecipientPairs = new HashSet<>();
    Stream.of(jobs).forEach(job -> {
        if (job instanceof MultiDeviceReadUpdateJob) {
            return;
        }
        Data data = job.serialize();
        long threadId = data.getLong("thread");
        String recipientId = data.getString("recipient");
        long[] messageIds = data.getLongArray("message_ids");
        assertEquals("Each job should contain two messages.", 2, messageIds.length);
        assertTrue("Each thread recipient pair should only exist once.", threadRecipientPairs.add(new Pair<>(threadId, recipientId)));
    });
    assertEquals("Should have 9 total combinations.", 9, threadRecipientPairs.size());
}
Also used : Context(android.content.Context) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) PowerMockito.mockStatic(org.powermock.api.mockito.PowerMockito.mockStatic) NonNull(androidx.annotation.NonNull) Data(org.thoughtcrime.securesms.jobmanager.Data) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) RunWith(org.junit.runner.RunWith) HashSet(java.util.HashSet) Answer(org.mockito.stubbing.Answer) Pair(org.whispersystems.libsignal.util.Pair) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest) Recipient(org.thoughtcrime.securesms.recipients.Recipient) PowerMockRunner(org.powermock.modules.junit4.PowerMockRunner) LinkedList(java.util.LinkedList) Before(org.junit.Before) MessageId(org.thoughtcrime.securesms.database.model.MessageId) PowerMockito.when(org.powermock.api.mockito.PowerMockito.when) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Set(java.util.Set) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Matchers.any(org.mockito.Matchers.any) List(java.util.List) PowerMockito.mock(org.powermock.api.mockito.PowerMockito.mock) MultiDeviceReadUpdateJob(org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob) PowerMockito.doAnswer(org.powermock.api.mockito.PowerMockito.doAnswer) Job(org.thoughtcrime.securesms.jobmanager.Job) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) Assert.assertEquals(org.junit.Assert.assertEquals) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Data(org.thoughtcrime.securesms.jobmanager.Data) MultiDeviceReadUpdateJob(org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob) Pair(org.whispersystems.libsignal.util.Pair) HashSet(java.util.HashSet) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest) Test(org.junit.Test)

Example 14 with Job

use of org.thoughtcrime.securesms.jobmanager.Job in project Signal-Android by WhisperSystems.

the class GroupsV2CapabilityChecker method refreshCapabilitiesIfNecessary.

/**
 * @param resolved A collection of resolved recipients.
 * @return True if a recipient needed to be refreshed, otherwise false.
 */
@WorkerThread
public static boolean refreshCapabilitiesIfNecessary(@NonNull Collection<Recipient> resolved) throws IOException {
    Set<RecipientId> needsRefresh = Stream.of(resolved).filter(r -> r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED).map(Recipient::getId).collect(Collectors.toSet());
    if (needsRefresh.size() > 0) {
        Log.d(TAG, "[refreshCapabilitiesIfNecessary] Need to refresh " + needsRefresh.size() + " recipients.");
        List<Job> jobs = RetrieveProfileJob.forRecipients(needsRefresh);
        JobManager jobManager = ApplicationDependencies.getJobManager();
        for (Job job : jobs) {
            if (!jobManager.runSynchronously(job, TimeUnit.SECONDS.toMillis(10)).isPresent()) {
                throw new IOException("Recipient capability was not retrieved in time");
            }
        }
        return true;
    } else {
        return false;
    }
}
Also used : RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) IOException(java.io.IOException) RetrieveProfileJob(org.thoughtcrime.securesms.jobs.RetrieveProfileJob) Job(org.thoughtcrime.securesms.jobmanager.Job) WorkerThread(androidx.annotation.WorkerThread)

Example 15 with Job

use of org.thoughtcrime.securesms.jobmanager.Job in project Signal-Android by WhisperSystems.

the class MessageDecryptionUtil method decrypt.

/**
 * Takes a {@link SignalServiceEnvelope} and returns a {@link DecryptionResult}, which has either
 * a plaintext {@link SignalServiceContent} or information about an error that happened.
 *
 * Excluding the data updated in our protocol stores that results from decrypting a message, this
 * method is side-effect free, preferring to return the decryption results to be handled by the
 * caller.
 */
@NonNull
public static DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
    SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
    SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireServiceId(), Recipient.self().requireE164());
    SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
    List<Job> jobs = new LinkedList<>();
    if (envelope.isPreKeySignalMessage()) {
        jobs.add(new RefreshPreKeysJob());
    }
    try {
        try {
            return DecryptionResult.forSuccess(cipher.decrypt(envelope), jobs);
        } catch (ProtocolInvalidVersionException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            return DecryptionResult.forError(MessageState.INVALID_VERSION, toExceptionMetadata(e), jobs);
        } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolUntrustedIdentityException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            Recipient sender = Recipient.external(context, e.getSender());
            if (sender.supportsMessageRetries() && Recipient.self().supportsMessageRetries() && FeatureFlags.retryReceipts()) {
                jobs.add(handleRetry(context, sender, envelope, e));
                postInternalErrorNotification(context);
            } else {
                jobs.add(new AutomaticSessionResetJob(sender.getId(), e.getSenderDevice(), envelope.getTimestamp()));
            }
            return DecryptionResult.forNoop(jobs);
        } catch (ProtocolLegacyMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.LEGACY_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (ProtocolDuplicateMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (InvalidMetadataVersionException | InvalidMetadataMessageException | InvalidMessageStructureException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forNoop(jobs);
        } catch (SelfSendException e) {
            Log.i(TAG, "Dropping UD message from self.");
            return DecryptionResult.forNoop(jobs);
        } catch (UnsupportedDataMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.UNSUPPORTED_DATA_MESSAGE, toExceptionMetadata(e), jobs);
        }
    } catch (NoSenderException e) {
        Log.w(TAG, "Invalid message, but no sender info!");
        return DecryptionResult.forNoop(jobs);
    }
}
Also used : ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) ProtocolUntrustedIdentityException(org.signal.libsignal.metadata.ProtocolUntrustedIdentityException) ProtocolInvalidVersionException(org.signal.libsignal.metadata.ProtocolInvalidVersionException) InvalidMessageStructureException(org.whispersystems.signalservice.api.InvalidMessageStructureException) SelfSendException(org.signal.libsignal.metadata.SelfSendException) ProtocolInvalidKeyIdException(org.signal.libsignal.metadata.ProtocolInvalidKeyIdException) ProtocolDuplicateMessageException(org.signal.libsignal.metadata.ProtocolDuplicateMessageException) UnsupportedDataMessageException(org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ProtocolLegacyMessageException(org.signal.libsignal.metadata.ProtocolLegacyMessageException) SignalServiceAccountDataStore(org.whispersystems.signalservice.api.SignalServiceAccountDataStore) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) SendRetryReceiptJob(org.thoughtcrime.securesms.jobs.SendRetryReceiptJob) Job(org.thoughtcrime.securesms.jobmanager.Job) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) ProtocolNoSessionException(org.signal.libsignal.metadata.ProtocolNoSessionException) SignalServiceCipher(org.whispersystems.signalservice.api.crypto.SignalServiceCipher) Recipient(org.thoughtcrime.securesms.recipients.Recipient) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) LinkedList(java.util.LinkedList) InvalidMetadataMessageException(org.signal.libsignal.metadata.InvalidMetadataMessageException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) InvalidMetadataVersionException(org.signal.libsignal.metadata.InvalidMetadataVersionException) NonNull(androidx.annotation.NonNull)

Aggregations

Job (org.thoughtcrime.securesms.jobmanager.Job)26 JobManager (org.thoughtcrime.securesms.jobmanager.JobManager)16 NonNull (androidx.annotation.NonNull)14 Recipient (org.thoughtcrime.securesms.recipients.Recipient)12 WorkerThread (androidx.annotation.WorkerThread)10 List (java.util.List)10 RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)10 Context (android.content.Context)8 Stream (com.annimon.stream.Stream)8 IOException (java.io.IOException)8 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)8 AttachmentCompressionJob (org.thoughtcrime.securesms.jobs.AttachmentCompressionJob)8 AttachmentCopyJob (org.thoughtcrime.securesms.jobs.AttachmentCopyJob)8 AttachmentMarkUploadedJob (org.thoughtcrime.securesms.jobs.AttachmentMarkUploadedJob)8 AttachmentUploadJob (org.thoughtcrime.securesms.jobs.AttachmentUploadJob)8 MmsSendJob (org.thoughtcrime.securesms.jobs.MmsSendJob)8 ProfileKeySendJob (org.thoughtcrime.securesms.jobs.ProfileKeySendJob)8 PushGroupSendJob (org.thoughtcrime.securesms.jobs.PushGroupSendJob)8 PushMediaSendJob (org.thoughtcrime.securesms.jobs.PushMediaSendJob)8 PushTextSendJob (org.thoughtcrime.securesms.jobs.PushTextSendJob)8