session-android/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
2016-12-20 09:55:52 -08:00

133 lines
5.2 KiB
Java

package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
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;
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;
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup;
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.inject.Inject;
public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements InjectableType {
private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceGroupUpdateJob.class.getSimpleName();
@Inject
transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory;
public MultiDeviceGroupUpdateJob(Context context) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withRequirement(new MasterSecretRequirement(context))
.withGroupId(MultiDeviceGroupUpdateJob.class.getSimpleName())
.withPersistence()
.create());
}
@Override
public void onRun(MasterSecret masterSecret) throws Exception {
SignalServiceMessageSender messageSender = messageSenderFactory.create();
File contactDataFile = createTempFile("multidevice-contact-update");
GroupDatabase.Reader reader = null;
GroupDatabase.GroupRecord record;
try {
DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(new FileOutputStream(contactDataFile));
reader = DatabaseFactory.getGroupDatabase(context).getGroups();
while ((record = reader.getNext()) != null) {
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
record.getMembers(), getAvatar(record.getAvatar()),
record.isActive()));
}
out.close();
if (contactDataFile.exists() && contactDataFile.length() > 0) {
sendUpdate(messageSender, contactDataFile);
} else {
Log.w(TAG, "No groups present for sync message...");
}
} finally {
if (contactDataFile != null) contactDataFile.delete();
if (reader != null) reader.close();
}
}
@Override
public boolean onShouldRetryThrowable(Exception exception) {
if (exception instanceof PushNetworkException) return true;
return false;
}
@Override
public void onAdded() {
}
@Override
public void onCanceled() {
}
private void sendUpdate(SignalServiceMessageSender messageSender, File contactsFile)
throws IOException, UntrustedIdentityException
{
FileInputStream contactsFileStream = new FileInputStream(contactsFile);
SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder()
.withStream(contactsFileStream)
.withContentType("application/octet-stream")
.withLength(contactsFile.length())
.build();
messageSender.sendMessage(SignalServiceSyncMessage.forGroups(attachmentStream));
}
private Optional<SignalServiceAttachmentStream> getAvatar(@Nullable byte[] avatar) {
if (avatar == null) return Optional.absent();
return Optional.of(SignalServiceAttachment.newStreamBuilder()
.withStream(new ByteArrayInputStream(avatar))
.withContentType("image/*")
.withLength(avatar.length)
.build());
}
private File createTempFile(String prefix) throws IOException {
File file = File.createTempFile(prefix, "tmp", context.getCacheDir());
file.deleteOnExit();
return file;
}
}