package org.thoughtcrime.securesms.jobs; import android.content.Context; import android.graphics.Bitmap; import android.util.Log; import org.thoughtcrime.securesms.Release; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.push.TextSecurePushTrustStore; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream; import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.exceptions.NonSuccessfulResponseCodeException; import java.io.File; import java.io.IOException; import java.io.InputStream; public class AvatarDownloadJob extends MasterSecretJob { private static final String TAG = AvatarDownloadJob.class.getSimpleName(); private final byte[] groupId; public AvatarDownloadJob(Context context, byte[] groupId) { super(context, JobParameters.newBuilder() .withRequirement(new MasterSecretRequirement(context)) .withRequirement(new NetworkRequirement(context)) .withPersistence() .create()); this.groupId = groupId; } @Override public void onAdded() {} @Override public void onRun(MasterSecret masterSecret) throws IOException { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); GroupDatabase.GroupRecord record = database.getGroup(groupId); File attachment = null; try { if (record != null) { long avatarId = record.getAvatarId(); byte[] key = record.getAvatarKey(); String relay = record.getRelay(); if (avatarId == -1 || key == null) { return; } attachment = downloadAttachment(relay, avatarId); InputStream scaleInputStream = new AttachmentCipherInputStream(attachment, key); InputStream measureInputStream = new AttachmentCipherInputStream(attachment, key); Bitmap avatar = BitmapUtil.createScaledBitmap(measureInputStream, scaleInputStream, 500, 500); database.updateAvatar(groupId, avatar); try { Recipient groupRecipient = RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(groupId), true) .getPrimaryRecipient(); groupRecipient.setContactPhoto(avatar); } catch (RecipientFormattingException e) { Log.w("AvatarDownloader", e); } } } catch (InvalidMessageException | BitmapDecodingException | NonSuccessfulResponseCodeException e) { Log.w(TAG, e); } finally { if (attachment != null) attachment.delete(); } } @Override public void onCanceled() {} @Override public boolean onShouldRetryThrowable(Throwable throwable) { if (throwable instanceof IOException) return true; return false; } private File downloadAttachment(String relay, long contentLocation) throws IOException { PushServiceSocket socket = new PushServiceSocket(Release.PUSH_URL, new TextSecurePushTrustStore(context), TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getPushServerPassword(context)); File destination = File.createTempFile("avatar", "tmp"); destination.deleteOnExit(); socket.retrieveAttachment(relay, contentLocation, destination); return destination; } }