diff --git a/res/drawable-hdpi/ic_call_secure_white_24dp.png b/res/drawable-hdpi/ic_call_secure_white_24dp.png new file mode 100644 index 0000000000..26050a12e8 Binary files /dev/null and b/res/drawable-hdpi/ic_call_secure_white_24dp.png differ diff --git a/res/drawable-mdpi/ic_call_secure_white_24dp.png b/res/drawable-mdpi/ic_call_secure_white_24dp.png new file mode 100644 index 0000000000..4f02407a64 Binary files /dev/null and b/res/drawable-mdpi/ic_call_secure_white_24dp.png differ diff --git a/res/drawable-xhdpi/ic_call_secure_white_24dp.png b/res/drawable-xhdpi/ic_call_secure_white_24dp.png new file mode 100644 index 0000000000..6c698b486b Binary files /dev/null and b/res/drawable-xhdpi/ic_call_secure_white_24dp.png differ diff --git a/res/drawable-xxhdpi/ic_call_secure_white_24dp.png b/res/drawable-xxhdpi/ic_call_secure_white_24dp.png new file mode 100644 index 0000000000..a5dee3398d Binary files /dev/null and b/res/drawable-xxhdpi/ic_call_secure_white_24dp.png differ diff --git a/res/menu/conversation_callable.xml b/res/menu/conversation_callable_insecure.xml similarity index 86% rename from res/menu/conversation_callable.xml rename to res/menu/conversation_callable_insecure.xml index fc027c8f47..009d7212b1 100644 --- a/res/menu/conversation_callable.xml +++ b/res/menu/conversation_callable_insecure.xml @@ -2,7 +2,7 @@ diff --git a/res/menu/conversation_callable_secure.xml b/res/menu/conversation_callable_secure.xml new file mode 100644 index 0000000000..3c5627e272 --- /dev/null +++ b/res/menu/conversation_callable_secure.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/res/menu/conversation_secure_sms.xml b/res/menu/conversation_secure.xml similarity index 100% rename from res/menu/conversation_secure_sms.xml rename to res/menu/conversation_secure.xml diff --git a/res/menu/conversation_secure_identity.xml b/res/menu/conversation_secure_identity.xml deleted file mode 100644 index a1623b622e..0000000000 --- a/res/menu/conversation_secure_identity.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 2694460863..f749215e28 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -659,6 +659,7 @@ Block Color Color for this contact + Verify identity Signal Call @@ -937,7 +938,7 @@ Refresh contact list - + Call @@ -993,7 +994,7 @@ Expand popup - + Add to contacts diff --git a/res/xml/recipient_preferences.xml b/res/xml/recipient_preferences.xml index 80f8423d71..7fcff5d3bc 100644 --- a/res/xml/recipient_preferences.xml +++ b/res/xml/recipient_preferences.xml @@ -36,9 +36,13 @@ android:persistent="false" app:numColumns="5" /> + + android:title="@string/recipient_preferences__block" + android:persistent="false"/> \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 6cbc25d1a5..c37ad74dcd 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -39,6 +39,7 @@ import android.support.v4.view.WindowCompat; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; +import android.util.Pair; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; @@ -84,8 +85,6 @@ import org.thoughtcrime.securesms.database.DraftDatabase.Draft; import org.thoughtcrime.securesms.database.DraftDatabase.Drafts; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.MmsSmsColumns.Types; -import org.thoughtcrime.securesms.database.NotInDirectoryException; -import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.mms.AttachmentManager; import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType; @@ -111,7 +110,8 @@ import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.DirectoryHelper; -import org.thoughtcrime.securesms.util.DirectoryHelper.RegistrationState; +import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities; +import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.GroupUtil; @@ -121,7 +121,6 @@ import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture; import org.whispersystems.libaxolotl.InvalidMessageException; -import org.whispersystems.textsecure.api.util.InvalidNumberException; import java.io.IOException; import java.security.NoSuchAlgorithmException; @@ -188,7 +187,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private Recipients recipients; private long threadId; private int distributionType; - private boolean isEncryptedConversation; + private boolean isSecureText; + private boolean isSecureVoice; private boolean isMmsEnabled = true; private DynamicTheme dynamicTheme = new DynamicTheme(); @@ -215,7 +215,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity initializeActionBar(); initializeViews(); initializeResources(); - initializeSecurity(false); + initializeSecurity(false, false); initializeDraft(); } @@ -231,7 +231,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity setIntent(intent); initializeResources(); - initializeSecurity(false); + initializeSecurity(false, false); initializeDraft(); if (fragment != null) { @@ -326,15 +326,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity MenuInflater inflater = this.getMenuInflater(); menu.clear(); - if (isSingleConversation() && isEncryptedConversation) { - inflater.inflate(R.menu.conversation_secure_identity, menu); - inflater.inflate(R.menu.conversation_secure_sms, menu.findItem(R.id.menu_security).getSubMenu()); - } else if (isSingleConversation()) { - inflater.inflate(R.menu.conversation_insecure, menu); - } - if (isSingleConversation()) { - inflater.inflate(R.menu.conversation_callable, menu); + if (isSecureVoice) inflater.inflate(R.menu.conversation_callable_secure, menu); + else inflater.inflate(R.menu.conversation_callable_insecure, menu); } else if (isGroupConversation()) { inflater.inflate(R.menu.conversation_group_options, menu); @@ -352,6 +346,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity inflater.inflate(R.menu.conversation, menu); + if (isSingleConversation() && isSecureText) { + inflater.inflate(R.menu.conversation_secure, menu); + } else if (isSingleConversation()) { + inflater.inflate(R.menu.conversation_insecure, menu); + } + if (recipients != null && recipients.isMuted()) inflater.inflate(R.menu.conversation_muted, menu); else inflater.inflate(R.menu.conversation_unmuted, menu); @@ -367,13 +367,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity public boolean onOptionsItemSelected(MenuItem item) { super.onOptionsItemSelected(item); switch (item.getItemId()) { - case R.id.menu_call: handleDial(getRecipients().getPrimaryRecipient()); return true; + case R.id.menu_call_secure: + case R.id.menu_call_insecure: handleDial(getRecipients().getPrimaryRecipient()); return true; case R.id.menu_delete_thread: handleDeleteThread(); return true; case R.id.menu_add_attachment: handleAddAttachment(); return true; case R.id.menu_view_media: handleViewMedia(); return true; case R.id.menu_add_to_contacts: handleAddToContacts(); return true; case R.id.menu_abort_session: handleAbortSecureSession(); return true; - case R.id.menu_verify_identity: handleVerifyIdentity(); return true; case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true; case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true; case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true; @@ -479,12 +479,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - private void handleVerifyIdentity() { - Intent verifyIdentityIntent = new Intent(this, VerifyIdentityActivity.class); - verifyIdentityIntent.putExtra("recipient", getRecipients().getPrimaryRecipient().getRecipientId()); - startActivity(verifyIdentityIntent); - } - private void handleAbortSecureSession() { AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(this); builder.setTitle(R.string.ConversationActivity_abort_secure_session_confirmation); @@ -607,30 +601,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void handleDial(final Recipient recipient) { if (recipient == null) return; - new AsyncTask() { - @Override - protected Boolean doInBackground(Recipient... params) { - try { - Context context = ConversationActivity.this; - Recipient recipient = params[0]; - String e164number = Util.canonicalizeNumber(context, recipient.getNumber()); - - return TextSecureDirectory.getInstance(context).isSecureVoiceSupported(e164number); - } catch (InvalidNumberException | NotInDirectoryException e) { - Log.w(TAG, e); - return false; - } - } - - @Override - protected void onPostExecute(Boolean secureVoiceSupported) { - handleDial(recipient, secureVoiceSupported); - } - }.execute(recipient); - } - - private void handleDial(Recipient recipient, boolean secureVoice) { - if (secureVoice) { + if (isSecureVoice) { Intent intent = new Intent(this, RedPhoneService.class); intent.setAction(RedPhoneService.ACTION_OUTGOING_CALL); intent.putExtra(RedPhoneService.EXTRA_REMOTE_NUMBER, recipient.getNumber()); @@ -687,7 +658,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } private void handleAddAttachment() { - if (this.isMmsEnabled || isEncryptedConversation) { + if (this.isMmsEnabled || isSecureText) { new AlertDialogWrapper.Builder(this).setAdapter(attachmentAdapter, new AttachmentTypeListener()) .show(); } else { @@ -703,17 +674,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity startActivity(intent); } - private void handleSecurityChange(boolean encryptedConversation) { - boolean isMediaMessage = !recipients.isSingleRecipient() || attachmentManager.isAttachmentPresent(); - this.isEncryptedConversation = encryptedConversation; + private void handleSecurityChange(boolean isSecureText, boolean isSecureVoice) { + this.isSecureText = isSecureText; + this.isSecureVoice = isSecureVoice; + + boolean isMediaMessage = !recipients.isSingleRecipient() || attachmentManager.isAttachmentPresent(); sendButton.resetAvailableTransports(isMediaMessage); - if (!isEncryptedConversation) sendButton.disableTransport(Type.TEXTSECURE); + if (!isSecureText) sendButton.disableTransport(Type.TEXTSECURE); if (recipients.isGroupRecipient()) sendButton.disableTransport(Type.SMS); - if (isEncryptedConversation) sendButton.setDefaultTransport(Type.TEXTSECURE); - else sendButton.setDefaultTransport(Type.SMS); + if (isSecureText) sendButton.setDefaultTransport(Type.TEXTSECURE); + else sendButton.setDefaultTransport(Type.SMS); calculateCharactersRemaining(); supportInvalidateOptionsMenu(); @@ -778,30 +751,38 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity }.execute(); } - private void initializeSecurity(final boolean current) { - handleSecurityChange(current || isGroupConversation()); + private void initializeSecurity(final boolean currentSecureText, + final boolean currentSecureVoice) + { + handleSecurityChange(currentSecureText || isGroupConversation(), + currentSecureVoice && !isGroupConversation()); - new AsyncTask() { + new AsyncTask>() { @Override - protected Boolean doInBackground(Recipients... params) { + protected Pair doInBackground(Recipients... params) { try { - Context context = ConversationActivity.this; - Recipients recipients = params[0]; - RegistrationState registrationState = DirectoryHelper.isTextSecureEnabledRecipient(context, recipients); + Context context = ConversationActivity.this; + Recipients recipients = params[0]; + UserCapabilities capabilities = DirectoryHelper.getUserCapabilities(context, recipients); + + if (capabilities.getTextCapability() == Capability.UNKNOWN || + capabilities.getVoiceCapability() == Capability.UNKNOWN) + { + capabilities = DirectoryHelper.refreshDirectoryFor(context, recipients); + } - if (registrationState == RegistrationState.NOT_REGISTERED) return false; - else if (registrationState == RegistrationState.REGISTERED) return true; - else return DirectoryHelper.refreshDirectoryFor(context, recipients) == RegistrationState.REGISTERED; + return new Pair<>(capabilities.getTextCapability() == Capability.SUPPORTED, + capabilities.getVoiceCapability() == Capability.SUPPORTED); } catch (IOException e) { Log.w(TAG, e); - return false; + return new Pair<>(false, false); } } @Override - protected void onPostExecute(Boolean result) { - if (current != result) { - handleSecurityChange(result); + protected void onPostExecute(Pair result) { + if (result.first != currentSecureText || result.second != currentSecureVoice) { + handleSecurityChange(result.first, result.second); } } }.execute(recipients); @@ -944,7 +925,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity securityUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - initializeSecurity(isEncryptedConversation); + initializeSecurity(isSecureText, isSecureVoice); calculateCharactersRemaining(); } }; @@ -1249,7 +1230,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(this, recipients, slideDeck, getMessage(), distributionType); - if (isEncryptedConversation && !forceSms) { + if (isSecureText && !forceSms) { outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessage); } @@ -1275,7 +1256,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity final Context context = getApplicationContext(); OutgoingTextMessage message; - if (isEncryptedConversation && !forceSms) { + if (isSecureText && !forceSms) { message = new OutgoingEncryptedMessage(recipients, getMessage()); } else { message = new OutgoingTextMessage(recipients, getMessage()); diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java index 38faea84ba..31aa8dbcf3 100644 --- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java +++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java @@ -173,7 +173,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { private static boolean isActiveInDirectory(Context context, Recipient recipient) { try { - if (!TextSecureDirectory.getInstance(context).isActiveNumber(Util.canonicalizeNumber(context, recipient.getNumber()))) { + if (!TextSecureDirectory.getInstance(context).isSecureTextSupported(Util.canonicalizeNumber(context, recipient.getNumber()))) { return false; } } catch (NotInDirectoryException e) { diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java index 932ecb15ae..2f039aa352 100644 --- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java +++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java @@ -44,11 +44,12 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi public static final String RECIPIENTS_EXTRA = "recipient_ids"; - private static final String PREFERENCE_MUTED = "pref_key_recipient_mute"; - private static final String PREFERENCE_TONE = "pref_key_recipient_ringtone"; - private static final String PREFERENCE_VIBRATE = "pref_key_recipient_vibrate"; - private static final String PREFERENCE_BLOCK = "pref_key_recipient_block"; - private static final String PREFERENCE_COLOR = "pref_key_recipient_color"; + private static final String PREFERENCE_MUTED = "pref_key_recipient_mute"; + private static final String PREFERENCE_TONE = "pref_key_recipient_ringtone"; + private static final String PREFERENCE_VIBRATE = "pref_key_recipient_vibrate"; + private static final String PREFERENCE_BLOCK = "pref_key_recipient_block"; + private static final String PREFERENCE_COLOR = "pref_key_recipient_color"; + private static final String PREFERENCE_IDENTITY = "pref_key_recipient_identity"; private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @@ -171,7 +172,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi .setOnPreferenceClickListener(new BlockClickedListener()); this.findPreference(PREFERENCE_COLOR) .setOnPreferenceChangeListener(new ColorChangeListener()); - } + this.findPreference(PREFERENCE_IDENTITY) + .setOnPreferenceClickListener(new IdentityClickedListener()); + } @Override public void onResume() { @@ -191,6 +194,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi ListPreference vibratePreference = (ListPreference) this.findPreference(PREFERENCE_VIBRATE); ColorPreference colorPreference = (ColorPreference) this.findPreference(PREFERENCE_COLOR); Preference blockPreference = this.findPreference(PREFERENCE_BLOCK); + Preference identityPreference = this.findPreference(PREFERENCE_IDENTITY); mutePreference.setChecked(recipients.isMuted()); @@ -222,8 +226,11 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi if (!recipients.isSingleRecipient() || recipients.isGroupRecipient()) { blockPreference.setEnabled(false); + identityPreference.setEnabled(false); } else { blockPreference.setEnabled(true); + identityPreference.setEnabled(true); + if (recipients.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock); else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block); } @@ -352,6 +359,17 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi } } + private class IdentityClickedListener implements Preference.OnPreferenceClickListener { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent verifyIdentityIntent = new Intent(getActivity(), VerifyIdentityActivity.class); + verifyIdentityIntent.putExtra("recipient", recipients.getPrimaryRecipient().getRecipientId()); + startActivity(verifyIdentityIntent); + + return true; + } + } + private class BlockClickedListener implements Preference.OnPreferenceClickListener { @Override public boolean onPreferenceClick(Preference preference) { diff --git a/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java b/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java index 7b41630535..5370fc0bd7 100644 --- a/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java +++ b/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java @@ -66,7 +66,7 @@ public class TextSecureDirectory { this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION); } - public boolean isActiveNumber(String e164number) throws NotInDirectoryException { + public boolean isSecureTextSupported(String e164number) throws NotInDirectoryException { if (e164number == null || e164number.length() == 0) { return false; } diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java index 517989ee5e..966c2f5739 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java @@ -63,7 +63,7 @@ public abstract class PushReceivedJob extends ContextJob { boolean isActiveNumber; try { - isActiveNumber = TextSecureDirectory.getInstance(context).isActiveNumber(e164number); + isActiveNumber = TextSecureDirectory.getInstance(context).isSecureTextSupported(e164number); } catch (NotInDirectoryException e) { isActiveNumber = false; } diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index a44ec759dd..0c3879c235 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -279,7 +279,7 @@ public class MessageSender { TextSecureDirectory directory = TextSecureDirectory.getInstance(context); try { - return directory.isActiveNumber(destination); + return directory.isSecureTextSupported(destination); } catch (NotInDirectoryException e) { try { TextSecureAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java index 8617c4d94f..e8a09b2567 100644 --- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java +++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java @@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; import org.thoughtcrime.securesms.recipients.Recipients; +import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability; import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.textsecure.api.TextSecureAccountManager; import org.whispersystems.textsecure.api.push.ContactTokenDetails; @@ -29,8 +30,30 @@ import java.util.Set; public class DirectoryHelper { - public enum RegistrationState { - REGISTERED, NOT_REGISTERED, UNKNOWN + public static class UserCapabilities { + + public static final UserCapabilities UNKNOWN = new UserCapabilities(Capability.UNKNOWN, Capability.UNKNOWN); + public static final UserCapabilities UNSUPPORTED = new UserCapabilities(Capability.UNSUPPORTED, Capability.UNSUPPORTED); + + public enum Capability { + UNKNOWN, SUPPORTED, UNSUPPORTED + } + + private final Capability text; + private final Capability voice; + + public UserCapabilities(Capability text, Capability voice) { + this.text = text; + this.voice = voice; + } + + public Capability getTextCapability() { + return text; + } + + public Capability getVoiceCapability() { + return voice; + } } private static final String TAG = DirectoryHelper.class.getSimpleName(); @@ -77,7 +100,7 @@ public class DirectoryHelper { } } - public static RegistrationState refreshDirectoryFor(Context context, Recipients recipients) + public static UserCapabilities refreshDirectoryFor(Context context, Recipients recipients) throws IOException { try { @@ -90,52 +113,55 @@ public class DirectoryHelper { if (details.isPresent()) { directory.setNumber(details.get(), true); ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context)); - return RegistrationState.REGISTERED; + return new UserCapabilities(Capability.SUPPORTED, details.get().isVoice() ? Capability.SUPPORTED : Capability.UNSUPPORTED); } else { ContactTokenDetails absent = new ContactTokenDetails(); absent.setNumber(number); directory.setNumber(absent, false); - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } } catch (InvalidNumberException e) { Log.w(TAG, e); - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } } - public static RegistrationState isTextSecureEnabledRecipient(Context context, Recipients recipients) { + public static UserCapabilities getUserCapabilities(Context context, Recipients recipients) { try { if (recipients == null) { - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } if (!TextSecurePreferences.isPushRegistered(context)) { - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } if (!recipients.isSingleRecipient()) { - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } if (recipients.isGroupRecipient()) { - return RegistrationState.REGISTERED; + return new UserCapabilities(Capability.SUPPORTED, Capability.UNSUPPORTED); } final String number = recipients.getPrimaryRecipient().getNumber(); if (number == null) { - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } - final String e164number = Util.canonicalizeNumber(context, number); + String e164number = Util.canonicalizeNumber(context, number); + boolean secureText = TextSecureDirectory.getInstance(context).isSecureTextSupported(e164number); + boolean secureVoice = TextSecureDirectory.getInstance(context).isSecureVoiceSupported(e164number); + + return new UserCapabilities(secureText ? Capability.SUPPORTED : Capability.UNSUPPORTED, + secureVoice ? Capability.SUPPORTED : Capability.UNSUPPORTED); - return TextSecureDirectory.getInstance(context).isActiveNumber(e164number) ? - RegistrationState.REGISTERED : RegistrationState.NOT_REGISTERED; } catch (InvalidNumberException e) { Log.w(TAG, e); - return RegistrationState.NOT_REGISTERED; + return UserCapabilities.UNSUPPORTED; } catch (NotInDirectoryException e) { - return RegistrationState.UNKNOWN; + return UserCapabilities.UNKNOWN; } }