2014-11-08 19:35:58 +00:00
|
|
|
package org.thoughtcrime.securesms.jobs;
|
|
|
|
|
|
|
|
import android.content.Context;
|
2017-08-15 01:11:13 +00:00
|
|
|
import android.text.TextUtils;
|
2014-11-08 19:35:58 +00:00
|
|
|
import android.util.Log;
|
|
|
|
|
2017-02-18 04:27:11 +00:00
|
|
|
import org.greenrobot.eventbus.EventBus;
|
2017-01-06 17:19:58 +00:00
|
|
|
import org.thoughtcrime.securesms.ApplicationContext;
|
|
|
|
import org.thoughtcrime.securesms.TextSecureExpiredException;
|
2015-10-13 01:25:05 +00:00
|
|
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
2014-12-12 09:03:24 +00:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
2017-07-26 16:59:15 +00:00
|
|
|
import org.thoughtcrime.securesms.database.Address;
|
2014-11-08 19:35:58 +00:00
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
2017-08-22 01:47:37 +00:00
|
|
|
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
2015-11-02 22:32:02 +00:00
|
|
|
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
2014-11-08 19:35:58 +00:00
|
|
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
2014-12-12 09:03:24 +00:00
|
|
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
2014-11-08 19:35:58 +00:00
|
|
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
2017-08-01 15:56:00 +00:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
2017-08-15 01:11:13 +00:00
|
|
|
import org.thoughtcrime.securesms.util.Base64;
|
2017-01-06 17:19:58 +00:00
|
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
2017-08-15 01:11:13 +00:00
|
|
|
import org.thoughtcrime.securesms.util.Util;
|
2014-11-08 19:35:58 +00:00
|
|
|
import org.whispersystems.jobqueue.JobParameters;
|
|
|
|
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
2016-03-23 17:34:41 +00:00
|
|
|
import org.whispersystems.libsignal.util.guava.Optional;
|
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
|
|
|
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
2014-11-08 19:35:58 +00:00
|
|
|
|
2014-12-12 09:03:24 +00:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
2014-11-08 19:35:58 +00:00
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2015-01-12 04:27:34 +00:00
|
|
|
public abstract class PushSendJob extends SendJob {
|
2014-11-08 19:35:58 +00:00
|
|
|
|
|
|
|
private static final String TAG = PushSendJob.class.getSimpleName();
|
|
|
|
|
|
|
|
protected PushSendJob(Context context, JobParameters parameters) {
|
|
|
|
super(context, parameters);
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:59:15 +00:00
|
|
|
protected static JobParameters constructParameters(Context context, Address destination) {
|
2014-11-08 19:35:58 +00:00
|
|
|
JobParameters.Builder builder = JobParameters.newBuilder();
|
|
|
|
builder.withPersistence();
|
2017-07-26 16:59:15 +00:00
|
|
|
builder.withGroupId(destination.serialize());
|
2014-11-08 19:35:58 +00:00
|
|
|
builder.withRequirement(new MasterSecretRequirement(context));
|
2015-03-11 21:23:45 +00:00
|
|
|
builder.withRequirement(new NetworkRequirement(context));
|
|
|
|
builder.withRetryCount(5);
|
2014-11-08 19:35:58 +00:00
|
|
|
|
|
|
|
return builder.create();
|
|
|
|
}
|
|
|
|
|
2017-01-06 17:19:58 +00:00
|
|
|
@Override
|
|
|
|
protected final void onSend(MasterSecret masterSecret) throws Exception {
|
|
|
|
if (TextSecurePreferences.getSignedPreKeyFailureCount(context) > 5) {
|
|
|
|
ApplicationContext.getInstance(context)
|
|
|
|
.getJobManager()
|
|
|
|
.add(new RotateSignedPreKeyJob(context));
|
|
|
|
|
|
|
|
throw new TextSecureExpiredException("Too many signed prekey rotation failures");
|
|
|
|
}
|
|
|
|
|
|
|
|
onPushSend(masterSecret);
|
|
|
|
}
|
|
|
|
|
2017-08-15 01:11:13 +00:00
|
|
|
protected Optional<byte[]> getProfileKey(Address address) {
|
|
|
|
try {
|
2017-08-22 01:47:37 +00:00
|
|
|
Optional<RecipientSettings> recipientsPreferences = DatabaseFactory.getRecipientDatabase(context)
|
|
|
|
.getRecipientSettings(address);
|
2017-08-15 01:11:13 +00:00
|
|
|
|
2017-08-17 04:49:41 +00:00
|
|
|
if (!recipientsPreferences.isPresent()) return Optional.absent();
|
2017-08-15 01:11:13 +00:00
|
|
|
|
2017-08-17 04:49:41 +00:00
|
|
|
boolean isSystemContact = !TextUtils.isEmpty(recipientsPreferences.get().getSystemDisplayName());
|
|
|
|
boolean isApproved = recipientsPreferences.get().isProfileSharing();
|
2017-08-15 01:11:13 +00:00
|
|
|
|
2017-08-17 04:49:41 +00:00
|
|
|
if (!isSystemContact & !isApproved) return Optional.absent();
|
|
|
|
|
|
|
|
String profileKey = TextSecurePreferences.getProfileKey(context);
|
|
|
|
|
|
|
|
if (profileKey == null) {
|
|
|
|
profileKey = Util.getSecret(32);
|
|
|
|
TextSecurePreferences.setProfileKey(context, profileKey);
|
2017-08-15 01:11:13 +00:00
|
|
|
}
|
|
|
|
|
2017-08-17 04:49:41 +00:00
|
|
|
return Optional.of(Base64.decode(profileKey));
|
2017-08-15 01:11:13 +00:00
|
|
|
} catch (IOException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-26 16:59:15 +00:00
|
|
|
protected SignalServiceAddress getPushAddress(Address address) {
|
2017-08-07 21:24:53 +00:00
|
|
|
// String relay = TextSecureDirectory.getInstance(context).getRelay(address.toPhoneString());
|
|
|
|
String relay = null;
|
2017-07-26 16:59:15 +00:00
|
|
|
return new SignalServiceAddress(address.toPhoneString(), Optional.fromNullable(relay));
|
2014-11-08 19:35:58 +00:00
|
|
|
}
|
|
|
|
|
2016-03-23 17:34:41 +00:00
|
|
|
protected List<SignalServiceAttachment> getAttachmentsFor(MasterSecret masterSecret, List<Attachment> parts) {
|
|
|
|
List<SignalServiceAttachment> attachments = new LinkedList<>();
|
2014-11-08 19:35:58 +00:00
|
|
|
|
2015-10-13 01:25:05 +00:00
|
|
|
for (final Attachment attachment : parts) {
|
2017-03-28 19:05:30 +00:00
|
|
|
try {
|
|
|
|
if (attachment.getDataUri() == null || attachment.getSize() == 0) throw new IOException("Assertion failed, outgoing attachment has no data!");
|
|
|
|
InputStream is = PartAuthority.getAttachmentStream(context, masterSecret, attachment.getDataUri());
|
|
|
|
attachments.add(SignalServiceAttachment.newStreamBuilder()
|
|
|
|
.withStream(is)
|
|
|
|
.withContentType(attachment.getContentType())
|
|
|
|
.withLength(attachment.getSize())
|
|
|
|
.withFileName(attachment.getFileName())
|
2017-05-12 05:46:35 +00:00
|
|
|
.withVoiceNote(attachment.isVoiceNote())
|
2017-03-28 19:05:30 +00:00
|
|
|
.withListener(new ProgressListener() {
|
|
|
|
@Override
|
|
|
|
public void onAttachmentProgress(long total, long progress) {
|
|
|
|
EventBus.getDefault().postSticky(new PartProgressEvent(attachment, total, progress));
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build());
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
Log.w(TAG, "Couldn't open attachment", ioe);
|
2014-11-08 19:35:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return attachments;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void notifyMediaMessageDeliveryFailed(Context context, long messageId) {
|
2017-08-01 15:56:00 +00:00
|
|
|
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
|
|
|
|
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
2014-11-08 19:35:58 +00:00
|
|
|
|
2017-08-01 15:56:00 +00:00
|
|
|
if (threadId != -1 && recipient != null) {
|
|
|
|
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
2015-04-14 17:01:33 +00:00
|
|
|
}
|
2014-11-08 19:35:58 +00:00
|
|
|
}
|
2017-01-06 17:19:58 +00:00
|
|
|
|
|
|
|
protected abstract void onPushSend(MasterSecret masterSecret) throws Exception;
|
2014-11-08 19:35:58 +00:00
|
|
|
}
|