use ConfirmIdentityDialog instead of ReceiveKeyDialog

also switch to AppCompatDialog
This commit is contained in:
agrajaghh
2015-05-21 19:13:03 +02:00
committed by Moxie Marlinspike
parent f1e8357131
commit 72bd6d5844
5 changed files with 21 additions and 248 deletions

View File

@@ -1,11 +1,11 @@
package org.thoughtcrime.securesms;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
@@ -53,15 +53,15 @@ public class ConfirmIdentityDialog extends AlertDialog {
SpannableString spannableString = new SpannableString(introduction + " " +
context.getString(R.string.ConfirmIdentityDialog_you_may_wish_to_verify_this_contact));
spannableString.setSpan(new VerifySpan(context, masterSecret, mismatch),
spannableString.setSpan(new VerifySpan(context, mismatch),
introduction.length()+1, spannableString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setTitle(name);
setMessage(spannableString);
setButton(AlertDialog.BUTTON_POSITIVE, "Accept", new AcceptListener(masterSecret, messageRecord, mismatch));
setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", new CancelListener());
setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ConfirmIdentityDialog_accept), new AcceptListener(masterSecret, messageRecord, mismatch));
setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(android.R.string.cancel), new CancelListener());
}
@Override
@@ -194,20 +194,17 @@ public class ConfirmIdentityDialog extends AlertDialog {
private static class VerifySpan extends ClickableSpan {
private final Context context;
private final MasterSecret masterSecret;
private final IdentityKeyMismatch mismatch;
private VerifySpan(Context context, MasterSecret masterSecret, IdentityKeyMismatch mismatch) {
this.context = context;
this.masterSecret = masterSecret;
this.mismatch = mismatch;
private VerifySpan(Context context, IdentityKeyMismatch mismatch) {
this.context = context;
this.mismatch = mismatch;
}
@Override
public void onClick(View widget) {
Intent intent = new Intent(context, VerifyIdentityActivity.class);
intent.putExtra("recipient", mismatch.getRecipientId());
intent.putExtra("master_secret", masterSecret);
intent.putExtra("remote_identity", new IdentityKeyParcelable(mismatch.getIdentityKey()));
context.startActivity(intent);
}

View File

@@ -43,6 +43,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
@@ -369,10 +370,21 @@ public class ConversationItem extends LinearLayout {
contactPhoto.setVisibility(View.VISIBLE);
}
private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
if (record.isIdentityMismatchFailure()) {
for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
if (mismatch.getRecipientId() == record.getIndividualRecipient().getRecipientId()) {
return mismatch;
}
}
}
return null;
}
/// Event handlers
private void handleKeyExchangeClicked() {
ReceiveKeyDialog.build(context, masterSecret, messageRecord).show();
new ConfirmIdentityDialog(context, masterSecret, messageRecord, getKeyMismatch(messageRecord)).show();
}
private class ThumbnailClickListener implements ThumbnailView.ThumbnailClickListener {

View File

@@ -1,210 +0,0 @@
/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.PushDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.jobs.PushDecryptJob;
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.ProgressDialogAsyncTask;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.libaxolotl.LegacyMessageException;
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
import org.whispersystems.libaxolotl.util.guava.Optional;
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
import org.whispersystems.textsecure.api.messages.TextSecureGroup;
import java.io.IOException;
/**
* Activity for displaying sent/received session keys.
*
* @author Moxie Marlinspike
*/
public class ReceiveKeyDialog extends MaterialDialog {
private static final String TAG = ReceiveKeyDialog.class.getSimpleName();
private ReceiveKeyDialog(Builder builder, MessageRecord messageRecord, IdentityKey identityKey) {
super(builder);
initializeText(messageRecord, identityKey);
}
public static @NonNull ReceiveKeyDialog build(@NonNull Context context,
@NonNull MasterSecret masterSecret,
@NonNull MessageRecord messageRecord)
{
try {
final IncomingPreKeyBundleMessage message = getMessage(messageRecord);
final IdentityKey identityKey = getIdentityKey(message);
Builder builder = new Builder(context).customView(R.layout.receive_key_dialog, true)
.positiveText(R.string.receive_key_dialog__complete)
.negativeText(android.R.string.cancel)
.callback(new ReceiveKeyDialogCallback(context,
masterSecret,
messageRecord,
message,
identityKey));
return new ReceiveKeyDialog(builder, messageRecord, identityKey);
} catch (InvalidKeyException | InvalidVersionException | InvalidMessageException | LegacyMessageException e) {
throw new AssertionError(e);
}
}
private void initializeText(final MessageRecord messageRecord, final IdentityKey identityKey) {
if (getCustomView() == null) {
throw new AssertionError("CustomView should not be null in ReceiveKeyDialog.");
}
TextView descriptionText = (TextView) getCustomView().findViewById(R.id.description_text);
String introText = getContext().getString(R.string.ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different);
SpannableString spannableString = new SpannableString(introText + " " +
getContext().getString(R.string.ReceiveKeyActivity_you_may_wish_to_verify_this_contact));
spannableString.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Intent intent = new Intent(getContext(), VerifyIdentityActivity.class);
intent.putExtra("recipient", messageRecord.getIndividualRecipient().getRecipientId());
intent.putExtra("remote_identity", new IdentityKeyParcelable(identityKey));
getContext().startActivity(intent);
}
}, introText.length() + 1,
spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
descriptionText.setText(spannableString);
descriptionText.setMovementMethod(LinkMovementMethod.getInstance());
}
private static IncomingPreKeyBundleMessage getMessage(MessageRecord messageRecord)
throws InvalidKeyException, InvalidVersionException,
InvalidMessageException, LegacyMessageException
{
IncomingTextMessage message = new IncomingTextMessage(messageRecord.getIndividualRecipient().getNumber(),
messageRecord.getRecipientDeviceId(),
System.currentTimeMillis(),
messageRecord.getBody().getBody(),
Optional.<TextSecureGroup>absent());
return new IncomingPreKeyBundleMessage(message, message.getMessageBody());
}
private static IdentityKey getIdentityKey(IncomingPreKeyBundleMessage message)
throws InvalidKeyException, InvalidVersionException,
InvalidMessageException, LegacyMessageException
{
try {
return new PreKeyWhisperMessage(Base64.decode(message.getMessageBody())).getIdentityKey();
} catch (IOException e) {
throw new AssertionError(e);
}
}
private static class ReceiveKeyDialogCallback extends ButtonCallback {
private Context context;
private MasterSecret masterSecret;
private MessageRecord messageRecord;
private IncomingPreKeyBundleMessage message;
private IdentityKey identityKey;
public ReceiveKeyDialogCallback(Context context,
MasterSecret masterSecret,
MessageRecord messageRecord,
IncomingPreKeyBundleMessage message,
IdentityKey identityKey)
{
this.context = context;
this.masterSecret = masterSecret;
this.messageRecord = messageRecord;
this.message = message;
this.identityKey = identityKey;
}
@Override public void onPositive(MaterialDialog dialog) {
new VerifyAsyncTask(context, masterSecret, messageRecord, message, identityKey).execute();
}
}
private static class VerifyAsyncTask extends ProgressDialogAsyncTask<Void,Void,Void> {
private MasterSecret masterSecret;
private MessageRecord messageRecord;
private IncomingPreKeyBundleMessage message;
private IdentityKey identityKey;
public VerifyAsyncTask(Context context,
MasterSecret masterSecret,
MessageRecord messageRecord,
IncomingPreKeyBundleMessage message,
IdentityKey identityKey)
{
super(context, R.string.ReceiveKeyActivity_processing, R.string.ReceiveKeyActivity_processing_key_exchange);
this.masterSecret = masterSecret;
this.messageRecord = messageRecord;
this.message = message;
this.identityKey = identityKey;
}
@Override
protected Void doInBackground(Void... params) {
if (getContext() == null) return null;
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(getContext());
PushDatabase pushDatabase = DatabaseFactory.getPushDatabase(getContext());
identityDatabase.saveIdentity(masterSecret,
messageRecord.getIndividualRecipient().getRecipientId(),
identityKey);
try {
byte[] body = Base64.decode(message.getMessageBody());
TextSecureEnvelope envelope = new TextSecureEnvelope(3, message.getSender(),
message.getSenderDeviceId(), "",
message.getSentTimestampMillis(),
body);
long pushId = pushDatabase.insert(envelope);
ApplicationContext.getInstance(getContext())
.getJobManager()
.add(new PushDecryptJob(getContext(), pushId, messageRecord.getId(), message.getSender()));
} catch (IOException e) {
throw new AssertionError(e);
}
return null;
}
}
}