From 7ba75c329108a65b9b57c1bcaf6470326a4c699b Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Wed, 15 Apr 2015 10:58:29 -0700 Subject: [PATCH] Use REST interface instead of WebSockets on GCM events. Closes #2994 // FREEBIE --- build.gradle | 12 ++-- .../TextSecureCommunicationModule.java | 8 +-- .../securesms/gcm/GcmBroadcastReceiver.java | 12 ++-- .../securesms/jobs/PushContentReceiveJob.java | 63 +++++++++++++++++++ .../jobs/PushNotificationReceiveJob.java | 52 +++++++++++++++ ...shReceiveJob.java => PushReceivedJob.java} | 54 +++------------- .../service/MessageRetrievalService.java | 4 +- 7 files changed, 140 insertions(+), 65 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java create mode 100644 src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java rename src/org/thoughtcrime/securesms/jobs/{PushReceiveJob.java => PushReceivedJob.java} (66%) diff --git a/build.gradle b/build.gradle index 596a14fae4..35230b7629 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ dependencies { compile 'org.whispersystems:jobmanager:0.11.0' compile 'org.whispersystems:libpastelog:1.0.6' - compile 'org.whispersystems:textsecure-android:1.2.5' + compile 'org.whispersystems:textsecure-android:1.3.0' androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' @@ -101,23 +101,23 @@ dependencyVerification { 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', 'org.whispersystems:jobmanager:ea9cb943c4892fb90c1eea1be30efeb85cefca213d52c788419553b58d0ed70d', 'org.whispersystems:libpastelog:550d33c565380d90f4c671e7b8ed5f3a6da55a9fda468373177106b2eb5220b2', - 'org.whispersystems:textsecure-android:39bb319e4c273145435f1a0947ddd7e09b891da9260281569351ecc81172dd84', + 'org.whispersystems:textsecure-android:df4c1ac9ee8f7cd43c8c07d64b16e31875e04632afc3fe73f2a47292a86c79a1', 'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', + 'org.whispersystems:textsecure-java:59d7c998c83a0f96bbc84db36719c9be8007bce16ee1ba9748af5610ab429656', 'org.whispersystems:axolotl-android:40d3db5004a84749a73f68d2f0d01b2ae35a73c54df96d8c6c6723b96efb6fc0', - 'org.whispersystems:textsecure-java:44d18618a5b6c3fc40a68efed7c486605d4726c38ea619245d57b7e0568b8cf6', - 'org.whispersystems:axolotl-java:6daee739b89d8d7101de6d98f77132fee48495c6ea647d880e77def842f999ea', - 'org.whispersystems:curve25519-android:3c29a4131a69b0d16baaa3d707678deb39602c3a3ffd75805ce7f9db252e5d0d', 'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', 'com.squareup.okhttp:okhttp:89b7f63e2e5b6c410266abc14f50fe52ea8d2d8a57260829e499b1cd9f0e61af', 'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d', - 'org.whispersystems:curve25519-java:9ccef8f5aba05d9942336f023c589d6278b4f9135bdc34a7bade1f4e7ad65fa3', + 'org.whispersystems:axolotl-java:6daee739b89d8d7101de6d98f77132fee48495c6ea647d880e77def842f999ea', + 'org.whispersystems:curve25519-android:3c29a4131a69b0d16baaa3d707678deb39602c3a3ffd75805ce7f9db252e5d0d', 'com.squareup.okio:okio:5e1098bd3fdee4c3347f5ab815b40ba851e4ab1b348c5e49a5b0362f0ce6e978', 'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94', 'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0', + 'org.whispersystems:curve25519-java:9ccef8f5aba05d9942336f023c589d6278b4f9135bdc34a7bade1f4e7ad65fa3', 'com.android.support:support-v4:703572d3015a088cc5604b7e38885af3d307c829d0c5ceaf8654ff41c71cd160', ] } diff --git a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java index 2405d51649..f8fcc60eea 100644 --- a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java @@ -11,13 +11,12 @@ import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob; import org.thoughtcrime.securesms.jobs.PushGroupSendJob; import org.thoughtcrime.securesms.jobs.PushMediaSendJob; +import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; +import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; import org.thoughtcrime.securesms.jobs.PushTextSendJob; import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; import org.thoughtcrime.securesms.push.SecurityEventListener; 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.service.MessageRetrievalService; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libaxolotl.util.guava.Optional; @@ -37,7 +36,8 @@ import dagger.Provides; PushMediaSendJob.class, AttachmentDownloadJob.class, RefreshPreKeysJob.class, - MessageRetrievalService.class}) + MessageRetrievalService.class, + PushNotificationReceiveJob.class}) public class TextSecureCommunicationModule { private final Context context; diff --git a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java index d15c786854..ac54bafd44 100644 --- a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java +++ b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java @@ -9,8 +9,8 @@ import android.util.Log; import com.google.android.gms.gcm.GoogleCloudMessaging; import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.jobs.PushReceiveJob; -import org.thoughtcrime.securesms.service.MessageRetrievalService; +import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; +import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; import org.thoughtcrime.securesms.util.TextSecurePreferences; public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { @@ -42,12 +42,12 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { private void handleReceivedMessage(Context context, String data) { ApplicationContext.getInstance(context) .getJobManager() - .add(new PushReceiveJob(context, data)); + .add(new PushContentReceiveJob(context, data)); } private void handleReceivedNotification(Context context) { - Intent intent = new Intent(context, MessageRetrievalService.class); - intent.setAction(MessageRetrievalService.ACTION_PUSH_RECEIVED); - startWakefulService(context, intent); + ApplicationContext.getInstance(context) + .getJobManager() + .add(new PushNotificationReceiveJob(context)); } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java new file mode 100644 index 0000000000..7869e42517 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java @@ -0,0 +1,63 @@ +package org.thoughtcrime.securesms.jobs; + +import android.content.Context; +import android.util.Log; + +import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.jobqueue.JobManager; +import org.whispersystems.jobqueue.JobParameters; +import org.whispersystems.libaxolotl.InvalidVersionException; +import org.whispersystems.textsecure.api.messages.TextSecureEnvelope; +import org.thoughtcrime.securesms.database.TextSecureDirectory; +import org.thoughtcrime.securesms.database.NotInDirectoryException; +import org.whispersystems.textsecure.api.push.ContactTokenDetails; + +import java.io.IOException; + +public class PushContentReceiveJob extends PushReceivedJob { + + private static final String TAG = PushContentReceiveJob.class.getSimpleName(); + + private final String data; + + public PushContentReceiveJob(Context context) { + super(context, JobParameters.newBuilder().create()); + this.data = null; + } + + public PushContentReceiveJob(Context context, String data) { + super(context, JobParameters.newBuilder() + .withPersistence() + .withWakeLock(true) + .create()); + + this.data = data; + } + + @Override + public void onAdded() {} + + @Override + public void onRun() { + try { + String sessionKey = TextSecurePreferences.getSignalingKey(context); + TextSecureEnvelope envelope = new TextSecureEnvelope(data, sessionKey); + + handle(envelope, true); + } catch (IOException | InvalidVersionException e) { + Log.w(TAG, e); + } + } + + @Override + public void onCanceled() { + + } + + @Override + public boolean onShouldRetry(Exception exception) { + return false; + } +} diff --git a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java new file mode 100644 index 0000000000..9c81b902d5 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java @@ -0,0 +1,52 @@ +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.textsecure.api.TextSecureMessageReceiver; +import org.whispersystems.textsecure.api.messages.TextSecureEnvelope; +import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +public class PushNotificationReceiveJob extends PushReceivedJob implements InjectableType { + + private static final String TAG = PushNotificationReceiveJob.class.getSimpleName(); + + @Inject transient TextSecureMessageReceiver receiver; + + public PushNotificationReceiveJob(Context context) { + super(context, JobParameters.newBuilder() + .withRequirement(new NetworkRequirement(context)) + .withWakeLock(true, 30, TimeUnit.SECONDS).create()); + } + + @Override + public void onAdded() {} + + @Override + public void onRun() throws IOException { + receiver.retrieveMessages(new TextSecureMessageReceiver.MessageReceivedCallback() { + @Override + public void onMessage(TextSecureEnvelope envelope) { + handle(envelope, false); + } + }); + } + + @Override + public boolean onShouldRetry(Exception e) { + return e instanceof PushNetworkException; + } + + @Override + public void onCanceled() { + Log.w(TAG, "***** Failed to download pending message!"); + } +} diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java similarity index 66% rename from src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java rename to src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java index 170bd2de1d..c7a34e5f59 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java @@ -5,60 +5,19 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.thoughtcrime.securesms.database.NotInDirectoryException; +import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.whispersystems.jobqueue.JobManager; import org.whispersystems.jobqueue.JobParameters; -import org.whispersystems.libaxolotl.InvalidVersionException; import org.whispersystems.textsecure.api.messages.TextSecureEnvelope; -import org.thoughtcrime.securesms.database.TextSecureDirectory; -import org.thoughtcrime.securesms.database.NotInDirectoryException; import org.whispersystems.textsecure.api.push.ContactTokenDetails; -import java.io.IOException; +public abstract class PushReceivedJob extends ContextJob { -public class PushReceiveJob extends ContextJob { + private static final String TAG = PushReceivedJob.class.getSimpleName(); - private static final String TAG = PushReceiveJob.class.getSimpleName(); - - private final String data; - - public PushReceiveJob(Context context) { - super(context, JobParameters.newBuilder().create()); - this.data = null; - } - - public PushReceiveJob(Context context, String data) { - super(context, JobParameters.newBuilder() - .withPersistence() - .withWakeLock(true) - .create()); - - this.data = data; - } - - @Override - public void onAdded() {} - - @Override - public void onRun() { - try { - String sessionKey = TextSecurePreferences.getSignalingKey(context); - TextSecureEnvelope envelope = new TextSecureEnvelope(data, sessionKey); - - handle(envelope, true); - } catch (IOException | InvalidVersionException e) { - Log.w(TAG, e); - } - } - - @Override - public void onCanceled() { - - } - - @Override - public boolean onShouldRetry(Exception exception) { - return false; + protected PushReceivedJob(Context context, JobParameters parameters) { + super(context, parameters); } public void handle(TextSecureEnvelope envelope, boolean sendExplicitReceipt) { @@ -105,4 +64,5 @@ public class PushReceiveJob extends ContextJob { return isActiveNumber; } + } diff --git a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java index f3427f668c..1eb29e633e 100644 --- a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java +++ b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java @@ -9,7 +9,7 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.gcm.GcmBroadcastReceiver; -import org.thoughtcrime.securesms.jobs.PushReceiveJob; +import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider; @@ -85,7 +85,7 @@ public class MessageRetrievalService extends Service implements Runnable, Inject public void onMessage(TextSecureEnvelope envelope) { Log.w(TAG, "Retrieved envelope! " + envelope.getSource()); - PushReceiveJob receiveJob = new PushReceiveJob(MessageRetrievalService.this); + PushContentReceiveJob receiveJob = new PushContentReceiveJob(MessageRetrievalService.this); receiveJob.handle(envelope, false); decrementPushReceived();