diff --git a/build.gradle b/build.gradle index eedd54e32c..5bae1a9504 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ dependencies { compile 'org.whispersystems:jobmanager:1.0.2' compile 'org.whispersystems:libpastelog:1.0.7' compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' - compile 'org.whispersystems:signal-service-android:2.4.2' + compile 'org.whispersystems:signal-service-android:2.4.3' compile 'com.h6ah4i.android.compat:mulsellistprefcompat:1.0.0' compile 'com.google.zxing:core:3.2.1' @@ -134,7 +134,7 @@ dependencyVerification { 'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181', 'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88', 'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb', - 'org.whispersystems:signal-service-android:c86041f97294f8ad701cdfe0c84e5558cdb856933753aaa4b8223b0fff25809f', + 'org.whispersystems:signal-service-android:59e4cec73b9160b7d7c073841318098d46f25c618561d457baf4e10775a6e7b1', 'com.h6ah4i.android.compat:mulsellistprefcompat:47167c5cb796de1a854788e9ff318358e36c8fb88123baaa6e38fb78511dfabe', 'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259', 'cn.carbswang.android:NumberPickerView:18b3c316d62c7c277978a8d4ed57a5b8f4e943762264960f579a8a549c756729', @@ -144,7 +144,7 @@ dependencyVerification { 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', 'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19', - 'org.whispersystems:signal-service-java:18ac4595da7ad24b4dae3d277ba0ab624440343490c164a0ed3cc00307388d8b', + 'org.whispersystems:signal-service-java:9e983922084ca2c8089de0a58d7f2032e50026c2456c2bf9dfb0a56ac46a5864', 'com.google.android.gms:play-services-basement:e1d29b21e02fd2a63e5a31807415cbb17a59568e27e3254181c01ffae10659bf', 'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0', 'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c', @@ -160,7 +160,6 @@ dependencyVerification { ] } - android { compileSdkVersion 24 buildToolsVersion '23.0.3' @@ -178,6 +177,9 @@ android { buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" buildConfigField "String", "TEXTSECURE_URL", "\"https://textsecure-service.whispersystems.org\"" + buildConfigField "String[]", "CENSORED_COUNTRIES", "{\"+20\", \"+971\"}" + buildConfigField "String", "UNCENSORED_FRONTING_HOST", "\"https://www.google.com\"" + buildConfigField "String", "CENSORED_REFLECTOR", "\"signal-reflector-meek.appspot.com\"" buildConfigField "String", "GIPHY_PROXY_HOST", "\"giphy-proxy-production.whispersystems.org\"" buildConfigField "int", "GIPHY_PROXY_PORT", "80" buildConfigField "String", "USER_AGENT", "\"OWA\"" diff --git a/res/raw/censorship_fronting.store b/res/raw/censorship_fronting.store new file mode 100644 index 0000000000..431b9c54f9 Binary files /dev/null and b/res/raw/censorship_fronting.store differ diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 7d9c329a68..06008006e7 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -26,7 +26,7 @@ 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.dependencies.SignalCommunicationModule; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.GcmRefreshJob; import org.thoughtcrime.securesms.jobs.persistence.EncryptingJobSerializer; @@ -126,7 +126,7 @@ public class ApplicationContext extends Application implements DependencyInjecto } private void initializeDependencyInjection() { - this.objectGraph = ObjectGraph.create(new TextSecureCommunicationModule(this), + this.objectGraph = ObjectGraph.create(new SignalCommunicationModule(this), new RedPhoneCommunicationModule(this), new AxolotlStorageModule(this)); } diff --git a/src/org/thoughtcrime/securesms/DeviceActivity.java b/src/org/thoughtcrime/securesms/DeviceActivity.java index 9d6382ff1b..2cea6f5f3d 100644 --- a/src/org/thoughtcrime/securesms/DeviceActivity.java +++ b/src/org/thoughtcrime/securesms/DeviceActivity.java @@ -16,7 +16,7 @@ import android.widget.Toast; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.qr.ScanListener; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.DynamicLanguage; @@ -146,7 +146,7 @@ public class DeviceActivity extends PassphraseRequiredActionBarActivity protected Integer doInBackground(Void... params) { try { Context context = DeviceActivity.this; - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); String verificationCode = accountManager.getNewDeviceVerificationCode(); String ephemeralId = uri.getQueryParameter("uuid"); String publicKeyEncoded = uri.getQueryParameter("pub_key"); diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java index c54d29e263..087855cd5e 100644 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java @@ -4,17 +4,17 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.os.Build; import android.os.Bundle; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; -import android.view.WindowManager; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; +import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; +import org.thoughtcrime.securesms.push.Censorship; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.MessageRetrievalService; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -57,7 +57,9 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA Log.w(TAG, "onResume()"); super.onResume(); KeyCachingService.registerPassphraseActivityStarted(this); - MessageRetrievalService.registerActivityStarted(this); + + if (!Censorship.isCensored(this)) MessageRetrievalService.registerActivityStarted(this); + else ApplicationContext.getInstance(this).getJobManager().add(new PushNotificationReceiveJob(this)); isVisible = true; } @@ -66,7 +68,8 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA Log.w(TAG, "onPause()"); super.onPause(); KeyCachingService.registerPassphraseActivityStopped(this); - MessageRetrievalService.registerActivityStopped(this); + + if (!Censorship.isCensored(this)) MessageRetrievalService.registerActivityStopped(this); isVisible = false; } diff --git a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java index 6f193b3bd7..e69a44f6fd 100644 --- a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java @@ -31,7 +31,7 @@ import android.widget.TextView; import android.widget.Toast; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.service.RegistrationService; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -518,7 +518,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity { @Override protected Integer doInBackground(Void... params) { try { - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context, e164number, password); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context, e164number, password); int registrationId = TextSecurePreferences.getLocalRegistrationId(context); accountManager.verifyAccountWithCode(code, signalingKey, registrationId, true); @@ -611,7 +611,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity { @Override protected Integer doInBackground(Void... params) { try { - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context, e164number, password); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context, e164number, password); accountManager.requestVoiceVerificationCode(); return SUCCESS; diff --git a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java similarity index 70% rename from src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java rename to src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index 46605418ee..ae11543e20 100644 --- a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -6,6 +6,7 @@ import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.DeviceListFragment; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; +import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob; @@ -22,15 +23,19 @@ import org.thoughtcrime.securesms.jobs.PushTextSendJob; import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; +import org.thoughtcrime.securesms.push.Censorship; +import org.thoughtcrime.securesms.push.SignalServiceTrustStore; +import org.thoughtcrime.securesms.push.CensorshipFrontingTrustStore; import org.thoughtcrime.securesms.push.SecurityEventListener; -import org.thoughtcrime.securesms.push.TextSecurePushTrustStore; import org.thoughtcrime.securesms.service.MessageRetrievalService; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageSender; +import org.whispersystems.signalservice.api.push.TrustStore; import org.whispersystems.signalservice.api.util.CredentialsProvider; +import org.whispersystems.signalservice.internal.push.SignalServiceUrl; import dagger.Module; import dagger.Provides; @@ -53,29 +58,40 @@ import dagger.Provides; RefreshAttributesJob.class, GcmRefreshJob.class, RequestGroupInfoJob.class, - PushGroupUpdateJob.class}) -public class TextSecureCommunicationModule { + PushGroupUpdateJob.class, + AvatarDownloadJob.class}) +public class SignalCommunicationModule { - private final Context context; + private final Context context; + private final SignalServiceUrl url; + private final TrustStore trustStore; - public TextSecureCommunicationModule(Context context) { - this.context = context; + public SignalCommunicationModule(Context context) { + this.context = context; + + if (Censorship.isCensored(context)) { + this.url = new SignalServiceUrl(BuildConfig.UNCENSORED_FRONTING_HOST, BuildConfig.CENSORED_REFLECTOR); + this.trustStore = new CensorshipFrontingTrustStore(context); + } else { + this.url = new SignalServiceUrl(BuildConfig.TEXTSECURE_URL, null); + this.trustStore = new SignalServiceTrustStore(context); + } } - @Provides SignalServiceAccountManager provideTextSecureAccountManager() { - return new SignalServiceAccountManager(BuildConfig.TEXTSECURE_URL, - new TextSecurePushTrustStore(context), + @Provides SignalServiceAccountManager provideSignalAccountManager() { + return new SignalServiceAccountManager(this.url, this.trustStore, TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getPushServerPassword(context), BuildConfig.USER_AGENT); } - @Provides TextSecureMessageSenderFactory provideTextSecureMessageSenderFactory() { - return new TextSecureMessageSenderFactory() { + @Provides + SignalMessageSenderFactory provideSignalMessageSenderFactory() { + return new SignalMessageSenderFactory() { @Override public SignalServiceMessageSender create() { - return new SignalServiceMessageSender(BuildConfig.TEXTSECURE_URL, - new TextSecurePushTrustStore(context), + return new SignalServiceMessageSender(SignalCommunicationModule.this.url, + SignalCommunicationModule.this.trustStore, TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getPushServerPassword(context), new SignalProtocolStoreImpl(context), @@ -85,14 +101,13 @@ public class TextSecureCommunicationModule { }; } - @Provides SignalServiceMessageReceiver provideTextSecureMessageReceiver() { - return new SignalServiceMessageReceiver(BuildConfig.TEXTSECURE_URL, - new TextSecurePushTrustStore(context), - new DynamicCredentialsProvider(context), - BuildConfig.USER_AGENT); + @Provides SignalServiceMessageReceiver provideSignalMessageReceiver() { + return new SignalServiceMessageReceiver(this.url, this.trustStore, + new DynamicCredentialsProvider(context), + BuildConfig.USER_AGENT); } - public static interface TextSecureMessageSenderFactory { + public static interface SignalMessageSenderFactory { public SignalServiceMessageSender create(); } diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java index eef39c6f1c..eb04e2710a 100644 --- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java @@ -4,30 +4,34 @@ import android.content.Context; import android.graphics.Bitmap; import android.util.Log; -import org.thoughtcrime.securesms.BuildConfig; 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.mms.AttachmentStreamUriLoader.AttachmentModel; -import org.thoughtcrime.securesms.push.TextSecurePushTrustStore; import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapUtil; -import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.whispersystems.libsignal.InvalidMessageException; +import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; -import org.whispersystems.signalservice.internal.push.PushServiceSocket; -import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider; import java.io.File; import java.io.IOException; -import java.util.concurrent.ExecutionException; +import java.io.InputStream; + +import javax.inject.Inject; public class AvatarDownloadJob extends MasterSecretJob { + private static final long serialVersionUID = 1L; + private static final String TAG = AvatarDownloadJob.class.getSimpleName(); + @Inject transient SignalServiceMessageReceiver receiver; + private final byte[] groupId; public AvatarDownloadJob(Context context, byte[] groupId) { @@ -51,20 +55,28 @@ public class AvatarDownloadJob extends MasterSecretJob { try { if (record != null) { - long avatarId = record.getAvatarId(); - byte[] key = record.getAvatarKey(); - String relay = record.getRelay(); + long avatarId = record.getAvatarId(); + String contentType = record.getAvatarContentType(); + byte[] key = record.getAvatarKey(); + String relay = record.getRelay(); if (avatarId == -1 || key == null) { return; } - attachment = downloadAttachment(relay, avatarId); - Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key), 500, 500); + + + attachment = File.createTempFile("avatar", "tmp", context.getCacheDir()); + attachment.deleteOnExit(); + + SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, relay); + InputStream inputStream = receiver.retrieveAttachment(pointer, attachment); + Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key), 500, 500); database.updateAvatar(groupId, avatar); + inputStream.close(); } - } catch (BitmapDecodingException | NonSuccessfulResponseCodeException e) { + } catch (BitmapDecodingException | NonSuccessfulResponseCodeException | InvalidMessageException e) { Log.w(TAG, e); } finally { if (attachment != null) @@ -81,21 +93,4 @@ public class AvatarDownloadJob extends MasterSecretJob { return false; } - private File downloadAttachment(String relay, long contentLocation) throws IOException { - PushServiceSocket socket = new PushServiceSocket(BuildConfig.TEXTSECURE_URL, - new TextSecurePushTrustStore(context), - new StaticCredentialsProvider(TextSecurePreferences.getLocalNumber(context), - TextSecurePreferences.getPushServerPassword(context), - null), - BuildConfig.USER_AGENT); - - File destination = File.createTempFile("avatar", "tmp"); - - destination.deleteOnExit(); - - socket.retrieveAttachment(relay, contentLocation, destination, null); - - return destination; - } - } diff --git a/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java index 8765fa53dc..066ba56dae 100644 --- a/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java @@ -17,13 +17,15 @@ import java.io.IOException; import javax.inject.Inject; -import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; public class DeliveryReceiptJob extends ContextJob implements InjectableType { + private static final long serialVersionUID = 1L; + private static final String TAG = DeliveryReceiptJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final String destination; private final long timestamp; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java index 8b1956a591..fff6c04876 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java @@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase; import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.BlockedReader; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.recipients.Recipients; import org.whispersystems.jobqueue.JobParameters; @@ -30,7 +30,7 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje private static final String TAG = MultiDeviceBlockedUpdateJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; public MultiDeviceBlockedUpdateJob(Context context) { super(context, JobParameters.newBuilder() diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java index 9ac4f2d865..5d0e889797 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java @@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; @@ -47,7 +47,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje private static final String TAG = MultiDeviceContactUpdateJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final long recipientId; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java index 2aacd90087..fa015fc32a 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java @@ -8,7 +8,7 @@ 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.TextSecureCommunicationModule; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; @@ -36,7 +36,7 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject private static final String TAG = MultiDeviceGroupUpdateJob.class.getSimpleName(); @Inject - transient TextSecureCommunicationModule.TextSecureMessageSenderFactory messageSenderFactory; + transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory; public MultiDeviceGroupUpdateJob(Context context) { super(context, JobParameters.newBuilder() diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java index 7ac4956584..9f2adacb61 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java @@ -6,7 +6,7 @@ import android.util.Log; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; @@ -32,7 +32,7 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta private final List messageIds; @Inject - transient TextSecureCommunicationModule.TextSecureMessageSenderFactory messageSenderFactory; + transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory; public MultiDeviceReadUpdateJob(Context context, List messageIds) { super(context, JobParameters.newBuilder() diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 6e3325b3ca..457f47bfbf 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -42,7 +42,7 @@ import javax.inject.Inject; import ws.com.google.android.mms.MmsException; -import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; public class PushGroupSendJob extends PushSendJob implements InjectableType { @@ -50,7 +50,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { private static final String TAG = PushGroupSendJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final long messageId; private final long filterRecipientId; diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java index b6b32b7724..19cbe42588 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java @@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -32,7 +32,7 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType { private static final long serialVersionUID = 0L; - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final String source; private final byte[] groupId; diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index af5d74758a..4422f9f64b 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -34,7 +34,7 @@ import javax.inject.Inject; import ws.com.google.android.mms.MmsException; -import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; public class PushMediaSendJob extends PushSendJob implements InjectableType { @@ -42,7 +42,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { private static final String TAG = PushMediaSendJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final long messageId; diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index 45d9145c53..4201167ba1 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -28,7 +28,7 @@ import java.io.IOException; import javax.inject.Inject; -import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; public class PushTextSendJob extends PushSendJob implements InjectableType { @@ -36,7 +36,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { private static final String TAG = PushTextSendJob.class.getSimpleName(); - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final long messageId; diff --git a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java index 4dae72c424..a2679d4ebd 100644 --- a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java @@ -4,9 +4,7 @@ import android.content.Context; import android.support.annotation.NonNull; import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; -import org.whispersystems.jobqueue.Job; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -27,7 +25,7 @@ public class RequestGroupInfoJob extends ContextJob implements InjectableType { private static final long serialVersionUID = 0L; - @Inject transient TextSecureMessageSenderFactory messageSenderFactory; + @Inject transient SignalMessageSenderFactory messageSenderFactory; private final String source; private final byte[] groupId; diff --git a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java index 030b75d79e..2d56e7a12a 100644 --- a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java @@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.RegistrationActivity; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactIdentityManager; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.util.guava.Optional; @@ -188,7 +188,7 @@ public class AdvancedPreferenceFragment extends PreferenceFragment { protected Integer doInBackground(Void... params) { try { Context context = getActivity(); - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); RedPhoneAccountManager redPhoneAccountManager = new RedPhoneAccountManager(BuildConfig.REDPHONE_MASTER_URL, new RedPhoneTrustStore(context), TextSecurePreferences.getLocalNumber(context), diff --git a/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java new file mode 100644 index 0000000000..c96b2d0fe2 --- /dev/null +++ b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java @@ -0,0 +1,50 @@ +package org.thoughtcrime.securesms.push; + +import android.content.Context; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.signalservice.api.SignalServiceAccountManager; +import org.whispersystems.signalservice.api.push.TrustStore; +import org.whispersystems.signalservice.internal.push.SignalServiceUrl; + +public class AccountManagerFactory { + + public static SignalServiceAccountManager createManager(Context context) { + return new SignalServiceAccountManager(getUrl(context), getTrustStore(context), + TextSecurePreferences.getLocalNumber(context), + TextSecurePreferences.getPushServerPassword(context), + BuildConfig.USER_AGENT); + } + + public static SignalServiceAccountManager createManager(Context context, String number, String password) { + return new SignalServiceAccountManager(getUrl(number), getTrustStore(context, number), + number, password, BuildConfig.USER_AGENT); + } + + private static SignalServiceUrl getUrl(@NonNull Context context) { + return getUrl(TextSecurePreferences.getLocalNumber(context)); + } + + private static TrustStore getTrustStore(@NonNull Context context) { + return getTrustStore(context, TextSecurePreferences.getLocalNumber(context)); + } + + private static SignalServiceUrl getUrl(@NonNull String number) { + if (Censorship.isCensored(number)) { + return new SignalServiceUrl(BuildConfig.UNCENSORED_FRONTING_HOST, BuildConfig.CENSORED_REFLECTOR); + } else { + return new SignalServiceUrl(BuildConfig.TEXTSECURE_URL, null); + } + } + + private static TrustStore getTrustStore(@NonNull Context context, @NonNull String number) { + if (Censorship.isCensored(number)) { + return new CensorshipFrontingTrustStore(context); + } else { + return new SignalServiceTrustStore(context); + } + } + +} diff --git a/src/org/thoughtcrime/securesms/push/Censorship.java b/src/org/thoughtcrime/securesms/push/Censorship.java new file mode 100644 index 0000000000..536f9e8914 --- /dev/null +++ b/src/org/thoughtcrime/securesms/push/Censorship.java @@ -0,0 +1,26 @@ +package org.thoughtcrime.securesms.push; + + +import android.content.Context; + +import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +public class Censorship { + + public static boolean isCensored(Context context) { + String localNumber = TextSecurePreferences.getLocalNumber(context); + return isCensored(localNumber); + } + + public static boolean isCensored(String localNumber) { + for (String censoredRegion : BuildConfig.CENSORED_COUNTRIES) { + if (localNumber.startsWith(censoredRegion)) { + return true; + } + } + + return false; + } + +} diff --git a/src/org/thoughtcrime/securesms/push/CensorshipFrontingTrustStore.java b/src/org/thoughtcrime/securesms/push/CensorshipFrontingTrustStore.java new file mode 100644 index 0000000000..e9ea80c61e --- /dev/null +++ b/src/org/thoughtcrime/securesms/push/CensorshipFrontingTrustStore.java @@ -0,0 +1,29 @@ +package org.thoughtcrime.securesms.push; + + +import android.content.Context; + +import org.thoughtcrime.securesms.R; +import org.whispersystems.signalservice.api.push.TrustStore; + +import java.io.InputStream; + +public class CensorshipFrontingTrustStore implements TrustStore { + + private final Context context; + + public CensorshipFrontingTrustStore(Context context) { + this.context = context.getApplicationContext(); + } + + @Override + public InputStream getKeyStoreInputStream() { + return context.getResources().openRawResource(R.raw.censorship_fronting); + } + + @Override + public String getKeyStorePassword() { + return "whisper"; + } + +} diff --git a/src/org/thoughtcrime/securesms/push/TextSecurePushTrustStore.java b/src/org/thoughtcrime/securesms/push/SignalServiceTrustStore.java similarity index 72% rename from src/org/thoughtcrime/securesms/push/TextSecurePushTrustStore.java rename to src/org/thoughtcrime/securesms/push/SignalServiceTrustStore.java index b403c332a2..f19691e9df 100644 --- a/src/org/thoughtcrime/securesms/push/TextSecurePushTrustStore.java +++ b/src/org/thoughtcrime/securesms/push/SignalServiceTrustStore.java @@ -4,15 +4,14 @@ import android.content.Context; import org.thoughtcrime.securesms.R; import org.whispersystems.signalservice.api.push.TrustStore; -import org.whispersystems.signalservice.internal.push.PushServiceSocket; import java.io.InputStream; -public class TextSecurePushTrustStore implements TrustStore { +public class SignalServiceTrustStore implements TrustStore { private final Context context; - public TextSecurePushTrustStore(Context context) { + public SignalServiceTrustStore(Context context) { this.context = context.getApplicationContext(); } diff --git a/src/org/thoughtcrime/securesms/push/TextSecureCommunicationFactory.java b/src/org/thoughtcrime/securesms/push/TextSecureCommunicationFactory.java deleted file mode 100644 index 9107e71b16..0000000000 --- a/src/org/thoughtcrime/securesms/push/TextSecureCommunicationFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.thoughtcrime.securesms.push; - -import android.content.Context; - -import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.signalservice.api.SignalServiceAccountManager; - -public class TextSecureCommunicationFactory { - - public static SignalServiceAccountManager createManager(Context context) { - return new SignalServiceAccountManager(BuildConfig.TEXTSECURE_URL, - new TextSecurePushTrustStore(context), - TextSecurePreferences.getLocalNumber(context), - TextSecurePreferences.getPushServerPassword(context), - BuildConfig.USER_AGENT); - } - - public static SignalServiceAccountManager createManager(Context context, String number, String password) { - return new SignalServiceAccountManager(BuildConfig.TEXTSECURE_URL, new TextSecurePushTrustStore(context), - number, password, BuildConfig.USER_AGENT); - } - -} diff --git a/src/org/thoughtcrime/securesms/service/RegistrationService.java b/src/org/thoughtcrime/securesms/service/RegistrationService.java index 49d3482761..bd5f282817 100644 --- a/src/org/thoughtcrime/securesms/service/RegistrationService.java +++ b/src/org/thoughtcrime/securesms/service/RegistrationService.java @@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.jobs.GcmRefreshJob; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.DirectoryHelper; @@ -161,7 +161,7 @@ public class RegistrationService extends Service { String signalingKey = intent.getStringExtra("signaling_key"); try { - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(this, number, password); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(this, number, password); handleCommonRegistration(accountManager, number, password, signalingKey); @@ -198,7 +198,7 @@ public class RegistrationService extends Service { initializeChallengeListener(); setState(new RegistrationState(RegistrationState.STATE_CONNECTING, number)); - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(this, number, password); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(this, number, password); accountManager.requestSmsVerificationCode(); setState(new RegistrationState(RegistrationState.STATE_VERIFYING, number)); diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index 2660a8a7e0..a08bcc1988 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -36,7 +36,7 @@ import org.thoughtcrime.securesms.jobs.PushMediaSendJob; import org.thoughtcrime.securesms.jobs.PushTextSendJob; import org.thoughtcrime.securesms.jobs.SmsSendJob; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.service.ExpiringMessageManager; @@ -296,7 +296,7 @@ public class MessageSender { return directory.isSecureTextSupported(destination); } catch (NotInDirectoryException e) { try { - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); Optional registeredUser = accountManager.getContact(destination); if (!registeredUser.isPresent()) { diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java index e808f5d4d1..709449fcae 100644 --- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java +++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java @@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.database.NotInDirectoryException; import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; import org.thoughtcrime.securesms.notifications.MessageNotifier; -import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.sms.IncomingJoinedMessage; import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability; @@ -70,7 +70,7 @@ public class DirectoryHelper { throws IOException { List newUsers = refreshDirectory(context, - TextSecureCommunicationFactory.createManager(context), + AccountManagerFactory.createManager(context), TextSecurePreferences.getLocalNumber(context)); if (!newUsers.isEmpty() && TextSecurePreferences.isMultiDevice(context)) { @@ -112,7 +112,7 @@ public class DirectoryHelper { { try { TextSecureDirectory directory = TextSecureDirectory.getInstance(context); - SignalServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); String number = Util.canonicalizeNumber(context, recipients.getPrimaryRecipient().getNumber()); Optional details = accountManager.getContact(number); diff --git a/test/unitTest/java/org/thoughtcrime/securesms/jobs/DeliveryReceiptJobTest.java b/test/unitTest/java/org/thoughtcrime/securesms/jobs/DeliveryReceiptJobTest.java index 9439f09011..ead94c85c0 100644 --- a/test/unitTest/java/org/thoughtcrime/securesms/jobs/DeliveryReceiptJobTest.java +++ b/test/unitTest/java/org/thoughtcrime/securesms/jobs/DeliveryReceiptJobTest.java @@ -4,7 +4,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.thoughtcrime.securesms.BaseUnitTest; -import org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory; +import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.NotFoundException; @@ -91,8 +91,8 @@ public class DeliveryReceiptJobTest extends BaseUnitTest { } @Provides - TextSecureMessageSenderFactory provideSignalServiceMessageSenderFactory() { - return new TextSecureMessageSenderFactory() { + SignalMessageSenderFactory provideSignalServiceMessageSenderFactory() { + return new SignalMessageSenderFactory() { @Override public SignalServiceMessageSender create() { return textSecureMessageSender;