use of androidx.annotation.WorkerThread in project Signal-Android by WhisperSystems.
the class RemoteDeleteSendJob method create.
@WorkerThread
@NonNull
public static RemoteDeleteSendJob create(@NonNull Context context, long messageId, boolean isMms) throws NoSuchMessageException {
MessageRecord message = isMms ? SignalDatabase.mms().getMessageRecord(messageId) : SignalDatabase.sms().getSmsMessage(messageId);
Recipient conversationRecipient = SignalDatabase.threads().getRecipientForThreadId(message.getThreadId());
if (conversationRecipient == null) {
throw new AssertionError("We have a message, but couldn't find the thread!");
}
List<RecipientId> recipients = conversationRecipient.isGroup() ? Stream.of(RecipientUtil.getEligibleForSending(conversationRecipient.getParticipants())).map(Recipient::getId).toList() : Stream.of(conversationRecipient.getId()).toList();
recipients.remove(Recipient.self().getId());
return new RemoteDeleteSendJob(messageId, isMms, recipients, recipients.size(), new Parameters.Builder().setQueue(conversationRecipient.getId().toQueueKey()).setLifespan(TimeUnit.DAYS.toMillis(1)).setMaxAttempts(Parameters.UNLIMITED).build());
}
use of androidx.annotation.WorkerThread in project Signal-Android by WhisperSystems.
the class RetrieveProfileJob method forRecipients.
/**
* Works for any RecipientId, whether it's an individual, group, or yourself.
*
* @return A list of length 2 or less. Two iff you are in the recipients.
*/
@WorkerThread
@NonNull
public static List<Job> forRecipients(@NonNull Set<RecipientId> recipientIds) {
Context context = ApplicationDependencies.getApplication();
Set<RecipientId> combined = new HashSet<>(recipientIds.size());
boolean includeSelf = false;
for (RecipientId recipientId : recipientIds) {
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.isSelf()) {
includeSelf = true;
} else if (recipient.isGroup()) {
List<Recipient> recipients = SignalDatabase.groups().getGroupMembers(recipient.requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
combined.addAll(Stream.of(recipients).map(Recipient::getId).toList());
} else {
combined.add(recipientId);
}
}
List<Job> jobs = new ArrayList<>(2);
if (includeSelf) {
jobs.add(new RefreshOwnProfileJob());
}
if (combined.size() > 0) {
jobs.add(new RetrieveProfileJob(combined));
}
return jobs;
}
use of androidx.annotation.WorkerThread 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 androidx.annotation.WorkerThread in project Signal-Android by WhisperSystems.
the class ProfileKeySendJob method create.
/**
* Suitable for a 1:1 conversation or a GV1 group only.
*
* @param queueLimits True if you only want one of these to be run per person after decryptions
* are drained, otherwise false.
*/
@WorkerThread
public static ProfileKeySendJob create(@NonNull Context context, long threadId, boolean queueLimits) {
Recipient conversationRecipient = SignalDatabase.threads().getRecipientForThreadId(threadId);
if (conversationRecipient == null) {
throw new AssertionError("We have a thread but no recipient!");
}
if (conversationRecipient.isPushV2Group()) {
throw new AssertionError("Do not send profile keys directly for GV2");
}
List<RecipientId> recipients = conversationRecipient.isGroup() ? Stream.of(RecipientUtil.getEligibleForSending(conversationRecipient.getParticipants())).map(Recipient::getId).toList() : Stream.of(conversationRecipient.getId()).toList();
recipients.remove(Recipient.self().getId());
if (queueLimits) {
return new ProfileKeySendJob(new Parameters.Builder().setQueue("ProfileKeySendJob_" + conversationRecipient.getId().toQueueKey()).setMaxInstancesForQueue(1).addConstraint(NetworkConstraint.KEY).addConstraint(DecryptionsDrainedConstraint.KEY).setLifespan(TimeUnit.DAYS.toMillis(1)).setMaxAttempts(Parameters.UNLIMITED).build(), threadId, recipients);
} else {
return new ProfileKeySendJob(new Parameters.Builder().setQueue(conversationRecipient.getId().toQueueKey()).addConstraint(NetworkConstraint.KEY).setLifespan(TimeUnit.DAYS.toMillis(1)).setMaxAttempts(Parameters.UNLIMITED).build(), threadId, recipients);
}
}
use of androidx.annotation.WorkerThread in project Signal-Android by WhisperSystems.
the class ProfileUtil method getAddressForRecipient.
@WorkerThread
@NonNull
public static MobileCoinPublicAddress getAddressForRecipient(@NonNull Recipient recipient) throws IOException, PaymentsAddressException {
ProfileKey profileKey;
try {
profileKey = getProfileKey(recipient);
} catch (IOException e) {
Log.w(TAG, "Profile key not available for " + recipient.getId());
throw new PaymentsAddressException(PaymentsAddressException.Code.NO_PROFILE_KEY);
}
ProfileAndCredential profileAndCredential = ProfileUtil.retrieveProfileSync(ApplicationDependencies.getApplication(), recipient, SignalServiceProfile.RequestType.PROFILE);
SignalServiceProfile profile = profileAndCredential.getProfile();
byte[] encryptedPaymentsAddress = profile.getPaymentAddress();
if (encryptedPaymentsAddress == null) {
Log.w(TAG, "Payments not enabled for " + recipient.getId());
throw new PaymentsAddressException(PaymentsAddressException.Code.NOT_ENABLED);
}
try {
IdentityKey identityKey = new IdentityKey(Base64.decode(profileAndCredential.getProfile().getIdentityKey()), 0);
ProfileCipher profileCipher = new ProfileCipher(profileKey);
byte[] decrypted = profileCipher.decryptWithLength(encryptedPaymentsAddress);
SignalServiceProtos.PaymentAddress paymentAddress = SignalServiceProtos.PaymentAddress.parseFrom(decrypted);
byte[] bytes = MobileCoinPublicAddressProfileUtil.verifyPaymentsAddress(paymentAddress, identityKey);
MobileCoinPublicAddress mobileCoinPublicAddress = MobileCoinPublicAddress.fromBytes(bytes);
if (mobileCoinPublicAddress == null) {
throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS);
}
return mobileCoinPublicAddress;
} catch (InvalidCiphertextException | IOException e) {
Log.w(TAG, "Could not decrypt payments address, ProfileKey may be outdated for " + recipient.getId(), e);
throw new PaymentsAddressException(PaymentsAddressException.Code.COULD_NOT_DECRYPT);
} catch (InvalidKeyException e) {
Log.w(TAG, "Could not verify payments address due to bad identity key " + recipient.getId(), e);
throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE);
}
}
Aggregations