Support for censorship circumvention in Egypt and UAE

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2016-12-20 09:55:52 -08:00
parent 777aeea138
commit 541718fd11
28 changed files with 220 additions and 125 deletions

View File

@ -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\""

Binary file not shown.

View File

@ -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));
}

View File

@ -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");

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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()

View File

@ -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<SerializableSyncMessageId> messageIds;
@Inject
transient TextSecureCommunicationModule.TextSecureMessageSenderFactory messageSenderFactory;
transient SignalCommunicationModule.SignalMessageSenderFactory messageSenderFactory;
public MultiDeviceReadUpdateJob(Context context, List<SyncMessageId> messageIds) {
super(context, JobParameters.newBuilder()

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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),

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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<ContactTokenDetails> registeredUser = accountManager.getContact(destination);
if (!registeredUser.isPresent()) {

View File

@ -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<String> 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<ContactTokenDetails> details = accountManager.getContact(number);

View File

@ -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;