Add transfer indicators for attachments

Closes #3498
// FREEBIE
This commit is contained in:
Jake McGinty
2015-06-26 20:14:51 -07:00
committed by Moxie Marlinspike
parent daa98107c3
commit c2e5f4e80a
51 changed files with 301 additions and 440 deletions

View File

@@ -3,10 +3,12 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.PartDatabase;
import org.thoughtcrime.securesms.database.PartDatabase.PartId;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.util.Base64;
@@ -15,6 +17,7 @@ import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.textsecure.api.TextSecureMessageReceiver;
import org.whispersystems.textsecure.api.messages.TextSecureAttachment.ProgressListener;
import org.whispersystems.textsecure.api.messages.TextSecureAttachmentPointer;
import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
@@ -26,6 +29,7 @@ import java.util.List;
import javax.inject.Inject;
import de.greenrobot.event.EventBus;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.PduPart;
@@ -82,15 +86,19 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
private void retrievePart(MasterSecret masterSecret, PduPart part, long messageId)
throws IOException
{
PartDatabase database = DatabaseFactory.getPartDatabase(context);
File attachmentFile = null;
PartDatabase.PartId partId = part.getPartId();
PartDatabase database = DatabaseFactory.getPartDatabase(context);
File attachmentFile = null;
final PartId partId = part.getPartId();
try {
attachmentFile = createTempFile();
TextSecureAttachmentPointer pointer = createAttachmentPointer(masterSecret, part);
InputStream attachment = messageReceiver.retrieveAttachment(pointer, attachmentFile);
InputStream attachment = messageReceiver.retrieveAttachment(pointer, attachmentFile, new ProgressListener() {
@Override public void onAttachmentProgress(long total, long progress) {
EventBus.getDefault().postSticky(new PartProgressEvent(partId, total, progress));
}
});
database.updateDownloadedPart(masterSecret, messageId, partId, part, attachment);
} catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException e) {
@@ -145,4 +153,5 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
private class InvalidPartException extends Exception {
public InvalidPartException(Exception e) {super(e);}
}
}

View File

@@ -96,7 +96,7 @@ public class AvatarDownloadJob extends MasterSecretJob {
destination.deleteOnExit();
socket.retrieveAttachment(relay, contentLocation, destination);
socket.retrieveAttachment(relay, contentLocation, destination, null);
return destination;
}

View File

@@ -103,7 +103,8 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
FileInputStream contactsFileStream = new FileInputStream(contactsFile);
TextSecureAttachmentStream attachmentStream = new TextSecureAttachmentStream(contactsFileStream,
"application/octet-stream",
contactsFile.length());
contactsFile.length(),
null);
try {
messageSender.sendMessage(TextSecureSyncMessage.forContacts(attachmentStream));
@@ -117,7 +118,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
try {
Uri displayPhotoUri = Uri.withAppendedPath(uri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
AssetFileDescriptor fd = context.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return Optional.of(new TextSecureAttachmentStream(fd.createInputStream(), "image/*", fd.getLength()));
return Optional.of(new TextSecureAttachmentStream(fd.createInputStream(), "image/*", fd.getLength(), null));
} catch (IOException e) {
Log.w(TAG, e);
}
@@ -140,7 +141,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
byte[] data = cursor.getBlob(0);
if (data != null) {
return Optional.of(new TextSecureAttachmentStream(new ByteArrayInputStream(data), "image/*", data.length));
return Optional.of(new TextSecureAttachmentStream(new ByteArrayInputStream(data), "image/*", data.length, null));
}
}

View File

@@ -95,7 +95,8 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
FileInputStream contactsFileStream = new FileInputStream(contactsFile);
TextSecureAttachmentStream attachmentStream = new TextSecureAttachmentStream(contactsFileStream,
"application/octet-stream",
contactsFile.length());
contactsFile.length(),
null);
messageSender.sendMessage(TextSecureSyncMessage.forGroups(attachmentStream));
}
@@ -105,7 +106,7 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
if (avatar == null) return Optional.absent();
return Optional.of(new TextSecureAttachmentStream(new ByteArrayInputStream(avatar),
"image/*", avatar.length));
"image/*", avatar.length, null));
}
private File createTempFile(String prefix) throws IOException {

View File

@@ -0,0 +1,15 @@
package org.thoughtcrime.securesms.jobs;
import org.thoughtcrime.securesms.database.PartDatabase.PartId;
public class PartProgressEvent {
public PartId partId;
public long total;
public long progress;
public PartProgressEvent(PartId partId, long total, long progress) {
this.partId = partId;
this.total = total;
this.progress = progress;
}
}

View File

@@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.PartDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.PartParser;
@@ -30,6 +31,7 @@ import java.util.List;
import javax.inject.Inject;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.SendReq;
import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory;
@@ -69,6 +71,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
database.markAsPush(messageId);
database.markAsSecure(messageId);
database.markAsSent(messageId, "push".getBytes(), 0);
updatePartsStatus(message.getBody());
} catch (InsecureFallbackApprovalException ifae) {
Log.w(TAG, ifae);
database.markAsPendingInsecureSmsFallback(messageId);
@@ -97,6 +100,13 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
notifyMediaMessageDeliveryFailed(context, messageId);
}
private void updatePartsStatus(PduBody body) {
if (body == null) return;
PartDatabase database = DatabaseFactory.getPartDatabase(context);
for (int i = 0; i < body.getPartsNum(); i++) {
database.markPartUploaded(messageId, body.getPart(i));
}
}
private void deliver(MasterSecret masterSecret, SendReq message)
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException,

View File

@@ -10,13 +10,12 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libaxolotl.util.guava.Optional;
import org.whispersystems.textsecure.api.messages.TextSecureAttachment;
import org.whispersystems.textsecure.api.messages.TextSecureAttachment.ProgressListener;
import org.whispersystems.textsecure.api.messages.TextSecureAttachmentStream;
import org.whispersystems.textsecure.api.push.TextSecureAddress;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
@@ -26,6 +25,7 @@ import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import de.greenrobot.event.EventBus;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendReq;
@@ -59,16 +59,19 @@ public abstract class PushSendJob extends SendJob {
List<TextSecureAttachment> attachments = new LinkedList<>();
for (int i=0;i<message.getBody().getPartsNum();i++) {
PduPart part = message.getBody().getPart(i);
String contentType = Util.toIsoString(part.getContentType());
final PduPart part = message.getBody().getPart(i);
final String contentType = Util.toIsoString(part.getContentType());
if (ContentType.isImageType(contentType) ||
ContentType.isAudioType(contentType) ||
ContentType.isVideoType(contentType))
{
try {
InputStream is = PartAuthority.getPartStream(context, masterSecret, part.getDataUri());
attachments.add(new TextSecureAttachmentStream(is, contentType, part.getDataSize()));
attachments.add(new TextSecureAttachmentStream(is, contentType, part.getDataSize(), new ProgressListener() {
@Override public void onAttachmentProgress(long total, long progress) {
EventBus.getDefault().postSticky(new PartProgressEvent(part.getPartId(), total, progress));
}
}));
} catch (IOException ioe) {
Log.w(TAG, "Couldn't open attachment", ioe);
}