diff --git a/build.gradle b/build.gradle index 375c0856dd..e78f8fb913 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.3' + compile 'org.whispersystems:signal-service-android:2.4.4' 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:59e4cec73b9160b7d7c073841318098d46f25c618561d457baf4e10775a6e7b1', + 'org.whispersystems:signal-service-android:27f3f686d9d9f855360307b4b641e666246e7b617020e271df66cb4bdcc26f2a', '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:9e983922084ca2c8089de0a58d7f2032e50026c2456c2bf9dfb0a56ac46a5864', + 'org.whispersystems:signal-service-java:df0e83633ff4078cd276838c8942b953f670c61a5f2615ae2a89c75c19fc1bec', 'com.google.android.gms:play-services-basement:e1d29b21e02fd2a63e5a31807415cbb17a59568e27e3254181c01ffae10659bf', 'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0', 'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c', @@ -176,10 +176,7 @@ android { vectorDrawables.useSupportLibrary = true buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" - buildConfigField "String", "TEXTSECURE_URL", "\"https://textsecure-service.whispersystems.org\"" - buildConfigField "String[]", "CENSORED_COUNTRIES", "{\"+20\", \"+971\", \"+53\", \"+968\"}" - buildConfigField "String", "UNCENSORED_FRONTING_HOST", "\"https://www.google.com\"" - buildConfigField "String", "CENSORED_REFLECTOR", "\"signal-reflector-meek.appspot.com\"" + buildConfigField "String", "SIGNAL_URL", "\"https://textsecure-service.whispersystems.org\"" buildConfigField "String", "GIPHY_PROXY_HOST", "\"giphy-proxy-production.whispersystems.org\"" buildConfigField "int", "GIPHY_PROXY_PORT", "80" buildConfigField "String", "USER_AGENT", "\"OWA\"" diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 06008006e7..09fbd009fa 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.jobs.persistence.EncryptingJobSerializer; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirementProvider; import org.thoughtcrime.securesms.jobs.requirements.MediaNetworkRequirementProvider; import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirementProvider; +import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobManager; @@ -126,7 +127,7 @@ public class ApplicationContext extends Application implements DependencyInjecto } private void initializeDependencyInjection() { - this.objectGraph = ObjectGraph.create(new SignalCommunicationModule(this), + this.objectGraph = ObjectGraph.create(new SignalCommunicationModule(this, new SignalServiceNetworkAccess(this)), new RedPhoneCommunicationModule(this), new AxolotlStorageModule(this)); } diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java index 087855cd5e..0d7d364d79 100644 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java @@ -14,7 +14,7 @@ import android.util.Log; 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.push.SignalServiceNetworkAccess; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.MessageRetrievalService; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -33,12 +33,14 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA private static final int STATE_PROMPT_PUSH_REGISTRATION = 4; private static final int STATE_EXPERIENCE_UPGRADE = 5; - private BroadcastReceiver clearKeyReceiver; - private boolean isVisible; + private SignalServiceNetworkAccess networkAccess; + private BroadcastReceiver clearKeyReceiver; + private boolean isVisible; @Override protected final void onCreate(Bundle savedInstanceState) { Log.w(TAG, "onCreate(" + savedInstanceState + ")"); + this.networkAccess = new SignalServiceNetworkAccess(this); onPreCreate(); final MasterSecret masterSecret = KeyCachingService.getMasterSecret(this); routeApplicationState(masterSecret); @@ -58,8 +60,9 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA super.onResume(); KeyCachingService.registerPassphraseActivityStarted(this); - if (!Censorship.isCensored(this)) MessageRetrievalService.registerActivityStarted(this); - else ApplicationContext.getInstance(this).getJobManager().add(new PushNotificationReceiveJob(this)); + if (!networkAccess.isCensored(this)) MessageRetrievalService.registerActivityStarted(this); + else ApplicationContext.getInstance(this).getJobManager().add(new PushNotificationReceiveJob(this)); + isVisible = true; } @@ -69,7 +72,8 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA super.onPause(); KeyCachingService.registerPassphraseActivityStopped(this); - if (!Censorship.isCensored(this)) MessageRetrievalService.registerActivityStopped(this); + if (!networkAccess.isCensored(this)) MessageRetrievalService.registerActivityStopped(this); + isVisible = false; } diff --git a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index ae11543e20..3002d78b8f 100644 --- a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -23,17 +23,14 @@ 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.SignalServiceNetworkAccess; 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; @@ -62,24 +59,16 @@ import dagger.Provides; AvatarDownloadJob.class}) public class SignalCommunicationModule { - private final Context context; - private final SignalServiceUrl url; - private final TrustStore trustStore; + private final Context context; + private final SignalServiceUrl[] urls; - 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); - } + public SignalCommunicationModule(Context context, SignalServiceNetworkAccess networkAccess) { + this.context = context; + this.urls = networkAccess.getConfiguration(context); } @Provides SignalServiceAccountManager provideSignalAccountManager() { - return new SignalServiceAccountManager(this.url, this.trustStore, + return new SignalServiceAccountManager(urls, TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getPushServerPassword(context), BuildConfig.USER_AGENT); @@ -90,8 +79,7 @@ public class SignalCommunicationModule { return new SignalMessageSenderFactory() { @Override public SignalServiceMessageSender create() { - return new SignalServiceMessageSender(SignalCommunicationModule.this.url, - SignalCommunicationModule.this.trustStore, + return new SignalServiceMessageSender(urls, TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getPushServerPassword(context), new SignalProtocolStoreImpl(context), @@ -102,7 +90,7 @@ public class SignalCommunicationModule { } @Provides SignalServiceMessageReceiver provideSignalMessageReceiver() { - return new SignalServiceMessageReceiver(this.url, this.trustStore, + return new SignalServiceMessageReceiver(urls, new DynamicCredentialsProvider(context), BuildConfig.USER_AGENT); } diff --git a/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java index c96b2d0fe2..694aa5db92 100644 --- a/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java +++ b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java @@ -1,50 +1,24 @@ 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), + return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(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), + return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(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 deleted file mode 100644 index 536f9e8914..0000000000 --- a/src/org/thoughtcrime/securesms/push/Censorship.java +++ /dev/null @@ -1,26 +0,0 @@ -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/GoogleFrontingTrustStore.java similarity index 80% rename from src/org/thoughtcrime/securesms/push/CensorshipFrontingTrustStore.java rename to src/org/thoughtcrime/securesms/push/GoogleFrontingTrustStore.java index e9ea80c61e..03167ec428 100644 --- a/src/org/thoughtcrime/securesms/push/CensorshipFrontingTrustStore.java +++ b/src/org/thoughtcrime/securesms/push/GoogleFrontingTrustStore.java @@ -8,11 +8,11 @@ import org.whispersystems.signalservice.api.push.TrustStore; import java.io.InputStream; -public class CensorshipFrontingTrustStore implements TrustStore { +public class GoogleFrontingTrustStore implements TrustStore { private final Context context; - public CensorshipFrontingTrustStore(Context context) { + public GoogleFrontingTrustStore(Context context) { this.context = context.getApplicationContext(); } diff --git a/src/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java b/src/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java new file mode 100644 index 0000000000..3f0def0f95 --- /dev/null +++ b/src/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java @@ -0,0 +1,77 @@ +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.push.TrustStore; +import org.whispersystems.signalservice.internal.push.SignalServiceUrl; + +import java.util.HashMap; +import java.util.Map; + +public class SignalServiceNetworkAccess { + + private static final String TAG = SignalServiceNetworkAccess.class.getName(); + + private static final String APPSPOT_REFLECTOR_HOST = "signal-reflector-meek.appspot.com"; + + private final Map censorshipConfiguration; + private final String[] censoredCountries; + private final SignalServiceUrl[] uncensoredConfiguration; + + public SignalServiceNetworkAccess(Context context) { + final TrustStore googleTrustStore = new GoogleFrontingTrustStore(context); + final SignalServiceUrl baseGoogle = new SignalServiceUrl("https://www.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore); + final SignalServiceUrl baseAndroid = new SignalServiceUrl("https://android.clients.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore); + + this.censorshipConfiguration = new HashMap() {{ + put("+20", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.eg", + APPSPOT_REFLECTOR_HOST, + googleTrustStore), + baseAndroid}); + + put("+971", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.ae", + APPSPOT_REFLECTOR_HOST, + googleTrustStore), + baseAndroid, baseGoogle}); + + put("+53", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.om", + APPSPOT_REFLECTOR_HOST, + googleTrustStore), + baseAndroid, baseGoogle}); + + put("+968", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.cu", + APPSPOT_REFLECTOR_HOST, + googleTrustStore), + baseAndroid, baseGoogle}); + }}; + + this.uncensoredConfiguration = new SignalServiceUrl[] { + new SignalServiceUrl(BuildConfig.SIGNAL_URL, new SignalServiceTrustStore(context)) + }; + + this.censoredCountries = this.censorshipConfiguration.keySet().toArray(new String[0]); + } + + public SignalServiceUrl[] getConfiguration(Context context) { + String localNumber = TextSecurePreferences.getLocalNumber(context); + return getConfiguration(localNumber); + } + + public SignalServiceUrl[] getConfiguration(String localNumber) { + for (String censoredRegion : this.censoredCountries) { + if (localNumber.startsWith(censoredRegion)) { + return this.censorshipConfiguration.get(censoredRegion); + } + } + + return this.uncensoredConfiguration; + } + + public boolean isCensored(Context context) { + return getConfiguration(context) != this.uncensoredConfiguration; + } + +}