Support for read receipts

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2017-09-15 22:38:53 -07:00
parent 65124fd1f2
commit cb9bc9659b
46 changed files with 471 additions and 451 deletions

View File

@@ -1,71 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
import javax.inject.Inject;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class DeliveryReceiptJob extends ContextJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = DeliveryReceiptJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
private final String destination;
private final long timestamp;
private final String relay;
public DeliveryReceiptJob(Context context, String destination, long timestamp, String relay) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withPersistence()
.withRetryCount(50)
.create());
this.destination = destination;
this.timestamp = timestamp;
this.relay = relay;
}
@Override
public void onAdded() {}
@Override
public void onRun() throws IOException {
Log.w("DeliveryReceiptJob", "Sending delivery receipt...");
SignalServiceMessageSender messageSender = messageSenderFactory.create();
SignalServiceAddress textSecureAddress = new SignalServiceAddress(destination, Optional.fromNullable(relay));
messageSender.sendDeliveryReceipt(textSecureAddress, timestamp);
}
@Override
public void onCanceled() {
Log.w(TAG, "Failed to send receipt after retry exhausted!");
}
@Override
public boolean onShouldRetry(Exception exception) {
Log.w(TAG, exception);
if (exception instanceof NonSuccessfulResponseCodeException) return false;
if (exception instanceof PushNetworkException) return true;
return false;
}
}

View File

@@ -7,7 +7,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.BlockedReader;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.jobqueue.JobParameters;
@@ -30,7 +29,7 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
private static final String TAG = MultiDeviceBlockedUpdateJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
public MultiDeviceBlockedUpdateJob(Context context) {
super(context, JobParameters.newBuilder()
@@ -45,10 +44,9 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
public void onRun(MasterSecret masterSecret)
throws IOException, UntrustedIdentityException
{
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
SignalServiceMessageSender messageSender = messageSenderFactory.create();
BlockedReader reader = database.readerForBlocked(database.getBlocked());
List<String> blocked = new LinkedList<>();
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
BlockedReader reader = database.readerForBlocked(database.getBlocked());
List<String> blocked = new LinkedList<>();
Recipient recipient;

View File

@@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Base64;
@@ -54,7 +53,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
private static final String TAG = MultiDeviceContactUpdateJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final @Nullable String address;
@@ -90,8 +89,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
private void generateSingleContactUpdate(@NonNull Address address)
throws IOException, UntrustedIdentityException, NetworkException
{
SignalServiceMessageSender messageSender = messageSenderFactory.create();
File contactDataFile = createTempFile("multidevice-contact-update");
File contactDataFile = createTempFile("multidevice-contact-update");
try {
DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactDataFile));
@@ -119,8 +117,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
private void generateFullContactUpdate()
throws IOException, UntrustedIdentityException, NetworkException
{
SignalServiceMessageSender messageSender = messageSenderFactory.create();
File contactDataFile = createTempFile("multidevice-contact-update");
File contactDataFile = createTempFile("multidevice-contact-update");
try {
DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactDataFile));

View File

@@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
@@ -38,8 +37,7 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceGroupUpdateJob.class.getSimpleName();
@Inject
transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
public MultiDeviceGroupUpdateJob(Context context) {
super(context, JobParameters.newBuilder()
@@ -52,9 +50,8 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
@Override
public void onRun(MasterSecret masterSecret) throws Exception {
SignalServiceMessageSender messageSender = messageSenderFactory.create();
File contactDataFile = createTempFile("multidevice-contact-update");
GroupDatabase.Reader reader = null;
File contactDataFile = createTempFile("multidevice-contact-update");
GroupDatabase.Reader reader = null;
GroupDatabase.GroupRecord record;

View File

@@ -7,11 +7,11 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
@@ -33,7 +33,7 @@ public class MultiDeviceProfileKeyUpdateJob extends MasterSecretJob implements I
private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceProfileKeyUpdateJob.class.getSimpleName();
@Inject SignalMessageSenderFactory messageSender;
@Inject transient SignalServiceMessageSender messageSender;
public MultiDeviceProfileKeyUpdateJob(Context context) {
super(context, JobParameters.newBuilder()
@@ -71,7 +71,7 @@ public class MultiDeviceProfileKeyUpdateJob extends MasterSecretJob implements I
SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, false));
messageSender.create().sendMessage(syncMessage);
messageSender.sendMessage(syncMessage);
}
@Override

View File

@@ -6,7 +6,6 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
@@ -31,8 +30,7 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
private final List<SerializableSyncMessageId> messageIds;
@Inject
transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
public MultiDeviceReadUpdateJob(Context context, List<SyncMessageId> messageIds) {
super(context, JobParameters.newBuilder()
@@ -62,7 +60,6 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
readMessages.add(new ReadMessage(messageId.sender, messageId.timestamp));
}
SignalServiceMessageSender messageSender = messageSenderFactory.create();
messageSender.sendMessage(SignalServiceSyncMessage.forRead(readMessages));
}

View File

@@ -7,7 +7,6 @@ import android.util.Log;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
@@ -30,7 +29,7 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
private static final String TAG = MultiDeviceVerifiedUpdateJob.class.getSimpleName();
@Inject
transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory;
transient SignalServiceMessageSender messageSender;
private final String destination;
private final byte[] identityKey;
@@ -65,7 +64,6 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
Address canonicalDestination = Address.fromSerialized(destination);
VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus);
SignalServiceMessageSender messageSender = messageSenderFactory.create();
VerifiedMessage verifiedMessage = new VerifiedMessage(canonicalDestination.toPhoneString(), new IdentityKey(identityKey, 0), verifiedState, timestamp);
messageSender.sendMessage(SignalServiceSyncMessage.forVerified(verifiedMessage));

View File

@@ -39,7 +39,7 @@ public class PushContentReceiveJob extends PushReceivedJob {
String sessionKey = TextSecurePreferences.getSignalingKey(context);
SignalServiceEnvelope envelope = new SignalServiceEnvelope(data, sessionKey);
handle(envelope, true);
handle(envelope);
} catch (IOException | InvalidVersionException e) {
Log.w(TAG, e);
}

View File

@@ -68,6 +68,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
import org.whispersystems.signalservice.api.messages.calls.AnswerMessage;
import org.whispersystems.signalservice.api.messages.calls.BusyMessage;
import org.whispersystems.signalservice.api.messages.calls.HangupMessage;
@@ -186,6 +187,11 @@ public class PushDecryptJob extends ContextJob {
else if (message.getIceUpdateMessages().isPresent()) handleCallIceUpdateMessage(envelope, message.getIceUpdateMessages().get());
else if (message.getHangupMessage().isPresent()) handleCallHangupMessage(envelope, message.getHangupMessage().get(), smsMessageId);
else if (message.getBusyMessage().isPresent()) handleCallBusyMessage(envelope, message.getBusyMessage().get());
} else if (content.getReceiptMessage().isPresent()) {
SignalServiceReceiptMessage message = content.getReceiptMessage().get();
if (message.isReadReceipt()) handleReadReceipt(envelope, message);
else if (message.isDeliveryReceipt()) handleDeliveryReceipt(envelope, message);
} else {
Log.w(TAG, "Got unrecognized message...");
}
@@ -824,6 +830,29 @@ public class PushDecryptJob extends ContextJob {
}
}
private void handleDeliveryReceipt(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceReceiptMessage message)
{
for (long timestamp : message.getTimestamps()) {
Log.w(TAG, String.format("Received encrypted delivery receipt: (XXXXX, %d)", timestamp));
DatabaseFactory.getMmsSmsDatabase(context)
.incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp));
}
}
private void handleReadReceipt(@NonNull SignalServiceEnvelope envelope,
@NonNull SignalServiceReceiptMessage message)
{
if (TextSecurePreferences.isReadReceiptsEnabled(context)) {
for (long timestamp : message.getTimestamps()) {
Log.w(TAG, String.format("Received encrypted read receipt: (XXXXX, %d)", timestamp));
DatabaseFactory.getMmsSmsDatabase(context)
.incrementReadReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp));
}
}
}
private Optional<InsertResult> insertPlaceholder(@NonNull SignalServiceEnvelope envelope) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),

View File

@@ -43,15 +43,13 @@ import java.util.List;
import javax.inject.Inject;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class PushGroupSendJob extends PushSendJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = PushGroupSendJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final long messageId;
private final long filterRecipientId; // Deprecated
@@ -137,7 +135,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
throws IOException, RecipientFormattingException, InvalidNumberException,
EncapsulatedExceptions, UndeliverableMessageException
{
SignalServiceMessageSender messageSender = messageSenderFactory.create();
String groupId = message.getRecipient().getAddress().toGroupString();
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
List<Recipient> recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);

View File

@@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
@@ -37,7 +36,7 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
private static final long serialVersionUID = 0L;
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final String source;
private final byte[] groupId;
@@ -59,10 +58,9 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
@Override
public void onRun() throws IOException, UntrustedIdentityException {
SignalServiceMessageSender messageSender = messageSenderFactory.create();
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
Optional<GroupRecord> record = groupDatabase.getGroup(GroupUtil.getEncodedId(groupId, false));
SignalServiceAttachment avatar = null;
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
Optional<GroupRecord> record = groupDatabase.getGroup(GroupUtil.getEncodedId(groupId, false));
SignalServiceAttachment avatar = null;
if (record == null) {
Log.w(TAG, "No information for group record info request: " + new String(groupId));

View File

@@ -32,15 +32,13 @@ import java.util.List;
import javax.inject.Inject;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class PushMediaSendJob extends PushSendJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = PushMediaSendJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final long messageId;
@@ -107,8 +105,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
throw new UndeliverableMessageException("No destination address.");
}
SignalServiceMessageSender messageSender = messageSenderFactory.create();
try {
SignalServiceAddress address = getPushAddress(message.getRecipient().getAddress());
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.util.Log;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
@@ -37,7 +36,7 @@ public class PushNotificationReceiveJob extends PushReceivedJob implements Injec
receiver.retrieveMessages(new SignalServiceMessageReceiver.MessageReceivedCallback() {
@Override
public void onMessage(SignalServiceEnvelope envelope) {
handle(envelope, false);
handle(envelope);
}
});
}

View File

@@ -9,17 +9,12 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import java.util.LinkedList;
public abstract class PushReceivedJob extends ContextJob {
private static final String TAG = PushReceivedJob.class.getSimpleName();
@@ -28,7 +23,7 @@ public abstract class PushReceivedJob extends ContextJob {
super(context, parameters);
}
public void handle(SignalServiceEnvelope envelope, boolean sendExplicitReceipt) {
public void handle(SignalServiceEnvelope envelope) {
Address source = Address.fromExternal(context, envelope.getSource());
Recipient recipient = Recipient.from(context, source, false);
@@ -40,13 +35,13 @@ public abstract class PushReceivedJob extends ContextJob {
if (envelope.isReceipt()) {
handleReceipt(envelope);
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
handleMessage(envelope, source, sendExplicitReceipt);
handleMessage(envelope, source);
} else {
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
}
}
private void handleMessage(SignalServiceEnvelope envelope, Address source, boolean sendExplicitReceipt) {
private void handleMessage(SignalServiceEnvelope envelope, Address source) {
Recipient recipients = Recipient.from(context, source, false);
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
@@ -56,12 +51,6 @@ public abstract class PushReceivedJob extends ContextJob {
} else {
Log.w(TAG, "*** Received blocked push message, ignoring...");
}
if (sendExplicitReceipt) {
jobManager.add(new DeliveryReceiptJob(context, envelope.getSource(),
envelope.getTimestamp(),
envelope.getRelay()));
}
}
private void handleReceipt(SignalServiceEnvelope envelope) {

View File

@@ -27,15 +27,13 @@ import java.io.IOException;
import javax.inject.Inject;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class PushTextSendJob extends PushSendJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = PushTextSendJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final long messageId;
@@ -101,7 +99,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
{
try {
SignalServiceAddress address = getPushAddress(message.getIndividualRecipient().getAddress());
SignalServiceMessageSender messageSender = messageSenderFactory.create();
Optional<byte[]> profileKey = getProfileKey(message.getIndividualRecipient());
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(message.getDateSent())

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@@ -25,7 +24,7 @@ public class RequestGroupInfoJob extends ContextJob implements InjectableType {
private static final long serialVersionUID = 0L;
@Inject transient SignalMessageSenderFactory messageSenderFactory;
@Inject transient SignalServiceMessageSender messageSender;
private final String source;
private final byte[] groupId;
@@ -46,16 +45,14 @@ public class RequestGroupInfoJob extends ContextJob implements InjectableType {
@Override
public void onRun() throws IOException, UntrustedIdentityException {
SignalServiceMessageSender messageSender = messageSenderFactory.create();
SignalServiceGroup group = SignalServiceGroup.newBuilder(Type.REQUEST_INFO)
.withId(groupId)
.build();
SignalServiceGroup group = SignalServiceGroup.newBuilder(Type.REQUEST_INFO)
.withId(groupId)
.build();
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
.asGroupMessage(group)
.withTimestamp(System.currentTimeMillis())
.build();
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
.asGroupMessage(group)
.withTimestamp(System.currentTimeMillis())
.build();
messageSender.sendMessage(new SignalServiceAddress(source), message);
}

View File

@@ -0,0 +1,69 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
import java.util.List;
import javax.inject.Inject;
public class SendReadReceiptJob extends ContextJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = SendReadReceiptJob.class.getSimpleName();
@Inject transient SignalServiceMessageSender messageSender;
private final String address;
private final List<Long> messageIds;
private final long timestamp;
public SendReadReceiptJob(Context context, Address address, List<Long> messageIds) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withPersistence()
.create());
this.address = address.serialize();
this.messageIds = messageIds;
this.timestamp = System.currentTimeMillis();
}
@Override
public void onAdded() {}
@Override
public void onRun() throws IOException, UntrustedIdentityException {
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) return;
SignalServiceAddress remoteAddress = new SignalServiceAddress(address);
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp);
messageSender.sendReceipt(remoteAddress, receiptMessage);
}
@Override
public boolean onShouldRetry(Exception e) {
if (e instanceof PushNetworkException) return true;
return false;
}
@Override
public void onCanceled() {
Log.w(TAG, "Failed to send read receipts to: " + address);
}
}