diff --git a/build.gradle b/build.gradle index e3ffcf0595..4c709a3301 100644 --- a/build.gradle +++ b/build.gradle @@ -75,10 +75,10 @@ dependencies { compile 'com.commonsware.cwac:camera:0.6.12' provided 'com.squareup.dagger:dagger-compiler:1.2.2' - compile 'org.whispersystems:jobmanager:0.11.0' + compile 'org.whispersystems:jobmanager:1.0.2' compile 'org.whispersystems:libpastelog:1.0.6' compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' - compile 'org.whispersystems:textsecure-android:1.8.0' + compile 'org.whispersystems:textsecure-android:1.8.1' compile 'com.h6ah4i.android.compat:mulsellistprefcompat:1.0.0' testCompile 'junit:junit:4.12' @@ -126,15 +126,12 @@ dependencyVerification { 'com.doomonafireball.betterpickers:library:132ecd685c95a99e7377c4e27bfadbb2d7ed0bea995944060cd62d4369fdaf3d', 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', 'com.commonsware.cwac:camera:dcc93ddbb2f0393114fa1f31a13fe9e6edfcf5dbe96b22bc4b66c7b15e179054', - 'org.whispersystems:jobmanager:ea9cb943c4892fb90c1eea1be30efeb85cefca213d52c788419553b58d0ed70d', 'org.whispersystems:libpastelog:550d33c565380d90f4c671e7b8ed5f3a6da55a9fda468373177106b2eb5220b2', 'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb', - 'org.whispersystems:textsecure-android:226214454003de852d856509ce9ca90a0865f7ad85a45f7a769916c6362fd4d7', 'com.h6ah4i.android.compat:mulsellistprefcompat:47167c5cb796de1a854788e9ff318358e36c8fb88123baaa6e38fb78511dfabe', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', - 'org.whispersystems:textsecure-java:97ef37e2ad88c6d7a896680bbab051ea894dc45409bc9b4683f75b55718fbeb5', 'org.whispersystems:axolotl-android:40d3db5004a84749a73f68d2f0d01b2ae35a73c54df96d8c6c6723b96efb6fc0', 'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', diff --git a/src/org/thoughtcrime/redphone/signaling/RedPhoneAccountManager.java b/src/org/thoughtcrime/redphone/signaling/RedPhoneAccountManager.java index d10215bcba..121f1232e9 100644 --- a/src/org/thoughtcrime/redphone/signaling/RedPhoneAccountManager.java +++ b/src/org/thoughtcrime/redphone/signaling/RedPhoneAccountManager.java @@ -60,6 +60,10 @@ public class RedPhoneAccountManager { Response response = client.newCall(builder.build()).execute(); + if (response.code() == 401 || response.code() == 403) { + throw new UnauthorizedException("Failed to perform GCM operation: " + response.code()); + } + if (!response.isSuccessful()) { throw new IOException("Failed to perform GCM operation: " + response.code()); } diff --git a/src/org/thoughtcrime/redphone/signaling/UnauthorizedException.java b/src/org/thoughtcrime/redphone/signaling/UnauthorizedException.java new file mode 100644 index 0000000000..ff4d3a0d30 --- /dev/null +++ b/src/org/thoughtcrime/redphone/signaling/UnauthorizedException.java @@ -0,0 +1,9 @@ +package org.thoughtcrime.redphone.signaling; + +import java.io.IOException; + +public class UnauthorizedException extends IOException { + public UnauthorizedException(String s) { + super(s); + } +} diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 2eeb5bd210..aaab48328d 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -25,8 +25,10 @@ import android.os.StrictMode.VmPolicy; import org.thoughtcrime.securesms.crypto.PRNGFixes; import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.dependencies.RedPhoneCommunicationModule; import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule; import org.thoughtcrime.securesms.jobs.GcmRefreshJob; +import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.jobs.persistence.EncryptingJobSerializer; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirementProvider; import org.thoughtcrime.securesms.jobs.requirements.MediaNetworkRequirementProvider; @@ -118,6 +120,7 @@ public class ApplicationContext extends Application implements DependencyInjecto private void initializeDependencyInjection() { this.objectGraph = ObjectGraph.create(new TextSecureCommunicationModule(this), + new RedPhoneCommunicationModule(this), new AxolotlStorageModule(this)); } diff --git a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java index 40733130ff..6570c6715d 100644 --- a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java +++ b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java @@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.PushDecryptJob; +import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.VersionTracker; @@ -67,6 +68,7 @@ public class DatabaseUpgradeActivity extends BaseActivity { public static final int MIGRATE_SESSION_PLAINTEXT = 136; public static final int CONTACTS_ACCOUNT_VERSION = 136; public static final int MEDIA_DOWNLOAD_CONTROLS_VERSION = 151; + public static final int REDPHONE_SUPPORT_VERSION = 157; private static final SortedSet UPGRADE_VERSIONS = new TreeSet() {{ add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION); @@ -79,6 +81,7 @@ public class DatabaseUpgradeActivity extends BaseActivity { add(PUSH_DECRYPT_SERIAL_ID_VERSION); add(MIGRATE_SESSION_PLAINTEXT); add(MEDIA_DOWNLOAD_CONTROLS_VERSION); + add(REDPHONE_SUPPORT_VERSION); }}; private MasterSecret masterSecret; @@ -220,6 +223,12 @@ public class DatabaseUpgradeActivity extends BaseActivity { schedulePendingIncomingParts(context); } + if (params[0] < REDPHONE_SUPPORT_VERSION) { + ApplicationContext.getInstance(getApplicationContext()) + .getJobManager() + .add(new RefreshAttributesJob(getApplicationContext())); + } + return null; } diff --git a/src/org/thoughtcrime/securesms/dependencies/RedPhoneCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/RedPhoneCommunicationModule.java new file mode 100644 index 0000000000..584f37a7f6 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dependencies/RedPhoneCommunicationModule.java @@ -0,0 +1,32 @@ +package org.thoughtcrime.securesms.dependencies; + +import android.content.Context; + +import org.thoughtcrime.redphone.signaling.RedPhoneAccountManager; +import org.thoughtcrime.redphone.signaling.RedPhoneTrustStore; +import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.jobs.GcmRefreshJob; +import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +import dagger.Module; +import dagger.Provides; + +@Module(complete = false, injects = {GcmRefreshJob.class, + RefreshAttributesJob.class}) +public class RedPhoneCommunicationModule { + + private final Context context; + + public RedPhoneCommunicationModule(Context context) { + this.context = context; + } + + @Provides RedPhoneAccountManager provideRedPhoneAccountManager() { + return new RedPhoneAccountManager(BuildConfig.REDPHONE_MASTER_URL, + new RedPhoneTrustStore(context), + TextSecurePreferences.getLocalNumber(context), + TextSecurePreferences.getPushServerPassword(context)); + } + +} diff --git a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java index 3c6ece846b..0d999b5728 100644 --- a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java @@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob; +import org.thoughtcrime.securesms.jobs.GcmRefreshJob; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob; import org.thoughtcrime.securesms.jobs.PushGroupSendJob; @@ -43,7 +44,8 @@ import dagger.Provides; MultiDeviceContactUpdateJob.class, MultiDeviceGroupUpdateJob.class, DeviceListActivity.DeviceListFragment.class, - RefreshAttributesJob.class}) + RefreshAttributesJob.class, + GcmRefreshJob.class}) public class TextSecureCommunicationModule { private final Context context; diff --git a/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java index 74e99ecfae..c704864bbb 100644 --- a/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java +++ b/src/org/thoughtcrime/securesms/jobs/GcmRefreshJob.java @@ -28,9 +28,11 @@ import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.gcm.GoogleCloudMessaging; +import org.thoughtcrime.redphone.signaling.RedPhoneAccountManager; +import org.thoughtcrime.redphone.signaling.UnauthorizedException; import org.thoughtcrime.securesms.PlayServicesProblemActivity; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; @@ -38,12 +40,17 @@ import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.textsecure.api.TextSecureAccountManager; import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException; -public class GcmRefreshJob extends ContextJob { +import javax.inject.Inject; + +public class GcmRefreshJob extends ContextJob implements InjectableType { private static final String TAG = GcmRefreshJob.class.getSimpleName(); public static final String REGISTRATION_ID = "312334754206"; + @Inject transient TextSecureAccountManager textSecureAccountManager; + @Inject transient RedPhoneAccountManager redPhoneAccountManager; + public GcmRefreshJob(Context context) { super(context, JobParameters.newBuilder().withRequirement(new NetworkRequirement(context)).create()); } @@ -53,8 +60,7 @@ public class GcmRefreshJob extends ContextJob { @Override public void onRun() throws Exception { - TextSecureAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); - String registrationId = TextSecurePreferences.getGcmRegistrationId(context); + String registrationId = TextSecurePreferences.getGcmRegistrationId(context); if (registrationId == null) { Log.w(TAG, "GCM registrationId expired, reregistering..."); @@ -64,7 +70,14 @@ public class GcmRefreshJob extends ContextJob { notifyGcmFailure(); } else { String gcmId = GoogleCloudMessaging.getInstance(context).register(REGISTRATION_ID); - accountManager.setGcmId(Optional.of(gcmId)); + textSecureAccountManager.setGcmId(Optional.of(gcmId)); + + try { + redPhoneAccountManager.setGcmId(Optional.of(gcmId)); + } catch (UnauthorizedException e) { + Log.w(TAG, e); + } + TextSecurePreferences.setGcmRegistrationId(context, gcmId); TextSecurePreferences.setWebsocketRegistered(context, true); } diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index f50f5068a6..654b3ce304 100644 --- a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -3,6 +3,9 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; import android.util.Log; +import org.thoughtcrime.redphone.signaling.RedPhoneAccountAttributes; +import org.thoughtcrime.redphone.signaling.RedPhoneAccountManager; +import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; @@ -13,11 +16,14 @@ import java.io.IOException; import javax.inject.Inject; -public class RefreshAttributesJob extends ContextJob { +public class RefreshAttributesJob extends ContextJob implements InjectableType { + + public static final long serialVersionUID = 1L; private static final String TAG = RefreshAttributesJob.class.getSimpleName(); - @Inject TextSecureAccountManager accountManager; + @Inject transient TextSecureAccountManager textSecureAccountManager; + @Inject transient RedPhoneAccountManager redPhoneAccountManager; public RefreshAttributesJob(Context context) { super(context, JobParameters.newBuilder() @@ -32,10 +38,14 @@ public class RefreshAttributesJob extends ContextJob { @Override public void onRun() throws IOException { - String signalingKey = TextSecurePreferences.getSignalingKey(context); - int registrationId = TextSecurePreferences.getLocalRegistrationId(context); + String signalingKey = TextSecurePreferences.getSignalingKey(context); + String gcmRegistrationId = TextSecurePreferences.getGcmRegistrationId(context); + int registrationId = TextSecurePreferences.getLocalRegistrationId(context); + + String token = textSecureAccountManager.getAccountVerificationToken(); - accountManager.setAccountAttributes(signalingKey, registrationId, true); + redPhoneAccountManager.createAccount(token, new RedPhoneAccountAttributes(signalingKey, gcmRegistrationId)); + textSecureAccountManager.setAccountAttributes(signalingKey, registrationId, true); } @Override