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);
}
}
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();
}
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());
}
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;
}
}
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);
}
}
Aggregations