mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-26 03:06:48 +00:00
Add support for SN verification
// FREEBIE
This commit is contained in:
@@ -85,11 +85,15 @@ import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer;
|
||||
import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer.AttachmentDrawerListener;
|
||||
import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer.DrawerState;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
|
||||
import org.thoughtcrime.securesms.components.identity.UntrustedSendDialog;
|
||||
import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView;
|
||||
import org.thoughtcrime.securesms.components.identity.UnverifiedSendDialog;
|
||||
import org.thoughtcrime.securesms.components.location.SignalPlace;
|
||||
import org.thoughtcrime.securesms.components.reminder.InviteReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.ReminderView;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
@@ -98,12 +102,16 @@ import org.thoughtcrime.securesms.database.DraftDatabase;
|
||||
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.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientPreferenceEvent;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.identity.IdentityRecordList;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
@@ -141,6 +149,7 @@ import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@@ -155,11 +164,13 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.thoughtcrime.securesms.TransportOption.Type;
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
/**
|
||||
@@ -199,19 +210,20 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private static final int PICK_GIF = 9;
|
||||
private static final int SMS_DEFAULT = 10;
|
||||
|
||||
private MasterSecret masterSecret;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private InputAwareLayout container;
|
||||
private View composePanel;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private MasterSecret masterSecret;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private InputAwareLayout container;
|
||||
private View composePanel;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private Stub<UnverifiedBannerView> unverifiedBannerView;
|
||||
|
||||
private AttachmentTypeSelector attachmentTypeSelector;
|
||||
private AttachmentManager attachmentManager;
|
||||
@@ -231,8 +243,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private boolean isDefaultSms = true;
|
||||
private boolean isMmsEnabled = true;
|
||||
|
||||
private DynamicTheme dynamicTheme = new DynamicTheme();
|
||||
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
private final IdentityRecordList identityRecords = new IdentityRecordList();
|
||||
private final DynamicTheme dynamicTheme = new DynamicTheme();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
@Override
|
||||
protected void onPreCreate() {
|
||||
@@ -308,6 +321,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
initializeEnabledCheck();
|
||||
initializeMmsEnabledCheck();
|
||||
initializeIdentityRecords();
|
||||
composeText.setTransport(sendButton.getSelectedTransport());
|
||||
|
||||
titleView.setTitle(recipients);
|
||||
@@ -317,7 +331,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
MessageNotifier.setVisibleThread(threadId);
|
||||
markThreadAsRead();
|
||||
markIdentitySeen();
|
||||
|
||||
Log.w(TAG, "onResume() Finished: " + (System.currentTimeMillis() - getIntent().getLongExtra(TIMING_EXTRA, 0)));
|
||||
}
|
||||
@@ -854,6 +867,56 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void handleUnverifiedRecipients() {
|
||||
List<Recipient> unverifiedRecipients = identityRecords.getUnverifiedRecipients(this);
|
||||
List<IdentityRecord> unverifiedRecords = identityRecords.getUnverifiedRecords();
|
||||
String message = IdentityUtil.getUnverifiedSendDialogDescription(this, unverifiedRecipients);
|
||||
|
||||
if (message == null) return;
|
||||
|
||||
new UnverifiedSendDialog(this, message, unverifiedRecords, new UnverifiedSendDialog.ResendListener() {
|
||||
@Override
|
||||
public void onResendMessage() {
|
||||
initializeIdentityRecords().addListener(new ListenableFuture.Listener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
sendMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void handleUntrustedRecipients() {
|
||||
List<Recipient> untrustedRecipients = identityRecords.getUntrustedRecipients(this);
|
||||
List<IdentityRecord> untrustedRecords = identityRecords.getUntrustedRecords();
|
||||
String untrustedMessage = IdentityUtil.getUntrustedSendDialogDescription(this, untrustedRecipients);
|
||||
|
||||
if (untrustedMessage == null) return;
|
||||
|
||||
new UntrustedSendDialog(this, untrustedMessage, untrustedRecords, new UntrustedSendDialog.ResendListener() {
|
||||
@Override
|
||||
public void onResendMessage() {
|
||||
initializeIdentityRecords().addListener(new ListenableFuture.Listener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
sendMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void handleSecurityChange(boolean isSecureText, boolean isDefaultSms) {
|
||||
this.isSecureText = isSecureText;
|
||||
this.isDefaultSms = isDefaultSms;
|
||||
@@ -1027,6 +1090,64 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private ListenableFuture<Boolean> initializeIdentityRecords() {
|
||||
final SettableFuture<Boolean> future = new SettableFuture<>();
|
||||
|
||||
new AsyncTask<Recipients, Void, Pair<IdentityRecordList, String>>() {
|
||||
@Override
|
||||
protected @NonNull Pair<IdentityRecordList, String> doInBackground(Recipients... params) {
|
||||
try {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(ConversationActivity.this);
|
||||
IdentityRecordList identityRecordList = new IdentityRecordList();
|
||||
Recipients recipients = params[0];
|
||||
|
||||
if (recipients.isGroupRecipient()) {
|
||||
recipients = DatabaseFactory.getGroupDatabase(ConversationActivity.this)
|
||||
.getGroupMembers(GroupUtil.getDecodedId(recipients.getPrimaryRecipient().getNumber()), false);
|
||||
}
|
||||
|
||||
for (long recipientId : recipients.getIds()) {
|
||||
Log.w(TAG, "Loading identity for: " + recipientId);
|
||||
identityRecordList.add(identityDatabase.getIdentity(recipientId));
|
||||
}
|
||||
|
||||
String message = null;
|
||||
|
||||
if (identityRecordList.isUnverified()) {
|
||||
message = IdentityUtil.getUnverifiedBannerDescription(ConversationActivity.this, identityRecordList.getUnverifiedRecipients(ConversationActivity.this));
|
||||
}
|
||||
|
||||
return new Pair<>(identityRecordList, message);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@NonNull Pair<IdentityRecordList, String> result) {
|
||||
Log.w(TAG, "Got identity records: " + result.first.isUnverified());
|
||||
identityRecords.replaceWith(result.first);
|
||||
|
||||
if (result.second != null) {
|
||||
Log.w(TAG, "Replacing banner...");
|
||||
unverifiedBannerView.get().display(result.second, result.first.getUnverifiedRecords(),
|
||||
new UnverifiedClickedListener(),
|
||||
new UnverifiedDismissedListener());
|
||||
} else if (unverifiedBannerView.resolved()) {
|
||||
Log.w(TAG, "Clearing banner...");
|
||||
unverifiedBannerView.get().hide();
|
||||
}
|
||||
|
||||
titleView.setVerified(identityRecords.isVerified());
|
||||
|
||||
future.set(true);
|
||||
}
|
||||
|
||||
}.execute(recipients);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
|
||||
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
|
||||
@@ -1040,6 +1161,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
container = ViewUtil.findById(this, R.id.layout_container);
|
||||
reminderView = ViewUtil.findStubById(this, R.id.reminder_stub);
|
||||
unverifiedBannerView = ViewUtil.findStubById(this, R.id.unverified_banner_stub);
|
||||
quickAttachmentDrawer = ViewUtil.findById(this, R.id.quick_attachment_drawer);
|
||||
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
|
||||
inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
@@ -1157,6 +1279,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void run() {
|
||||
titleView.setTitle(recipients);
|
||||
titleView.setVerified(identityRecords.isVerified());
|
||||
setBlockedUserState(recipients, isSecureText, isDefaultSms);
|
||||
setActionBarColor(recipients.getColor());
|
||||
invalidateOptionsMenu();
|
||||
@@ -1172,6 +1295,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onIdentityRecordUpdate(final IdentityRecord event) {
|
||||
initializeIdentityRecords();
|
||||
}
|
||||
|
||||
private void initializeReceivers() {
|
||||
securityUpdateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -1443,17 +1571,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}.execute(threadId);
|
||||
}
|
||||
|
||||
private void markIdentitySeen() {
|
||||
new AsyncTask<Recipient, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Recipient... params) {
|
||||
DatabaseFactory.getIdentityDatabase(ConversationActivity.this)
|
||||
.setSeen(params[0].getRecipientId());
|
||||
return null;
|
||||
}
|
||||
}.execute(recipients.getPrimaryRecipient());
|
||||
}
|
||||
|
||||
protected void sendComplete(long threadId) {
|
||||
boolean refreshFragment = (threadId != this.threadId);
|
||||
this.threadId = threadId;
|
||||
@@ -1490,6 +1607,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
|
||||
handleManualMmsRequired();
|
||||
} else if (!forceSms && identityRecords.isUnverified()) {
|
||||
handleUnverifiedRecipients();
|
||||
} else if (!forceSms && identityRecords.isUntrusted()) {
|
||||
handleUntrustedRecipients();
|
||||
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
|
||||
sendMediaMessage(forceSms, expiresIn, subscriptionId);
|
||||
} else {
|
||||
@@ -1886,4 +2007,68 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class UnverifiedDismissedListener implements UnverifiedBannerView.DismissListener {
|
||||
@Override
|
||||
public void onDismissed(final List<IdentityRecord> unverifiedIdentities) {
|
||||
final IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(ConversationActivity.this);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
synchronized (SESSION_LOCK) {
|
||||
for (IdentityRecord identityRecord : unverifiedIdentities) {
|
||||
identityDatabase.setVerified(identityRecord.getRecipientId(),
|
||||
identityRecord.getIdentityKey(),
|
||||
VerifiedStatus.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
initializeIdentityRecords();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private class UnverifiedClickedListener implements UnverifiedBannerView.ClickListener {
|
||||
@Override
|
||||
public void onClicked(final List<IdentityRecord> unverifiedIdentities) {
|
||||
Log.w(TAG, "onClicked: " + unverifiedIdentities.size());
|
||||
if (unverifiedIdentities.size() == 1) {
|
||||
Intent intent = new Intent(ConversationActivity.this, VerifyIdentityActivity.class);
|
||||
intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID_EXTRA, unverifiedIdentities.get(0).getRecipientId());
|
||||
intent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(unverifiedIdentities.get(0).getIdentityKey()));
|
||||
intent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, false);
|
||||
|
||||
startActivity(intent);
|
||||
} else {
|
||||
String[] unverifiedNames = new String[unverifiedIdentities.size()];
|
||||
|
||||
for (int i=0;i<unverifiedIdentities.size();i++) {
|
||||
unverifiedNames[i] = RecipientFactory.getRecipientForId(ConversationActivity.this, unverifiedIdentities.get(i).getRecipientId(), false).toShortString();
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ConversationActivity.this);
|
||||
builder.setIconAttribute(R.attr.dialog_alert_icon);
|
||||
builder.setTitle("No longer verified");
|
||||
builder.setItems(unverifiedNames, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(ConversationActivity.this, VerifyIdentityActivity.class);
|
||||
intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID_EXTRA, unverifiedIdentities.get(which).getRecipientId());
|
||||
intent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(unverifiedIdentities.get(which).getIdentityKey()));
|
||||
intent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, false);
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user