Add correct contextual menu options on 'Send' button.

[Send TextSecure message | Send unencrypted SMS | Send encrypted SMS]

// FREEBIE
master
Moxie Marlinspike 2014-06-11 15:31:59 -07:00
parent 7c9282f306
commit 68747142d6
13 changed files with 107 additions and 55 deletions

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_button_context__menu_send_unencrypted"
android:id="@+id/menu_context_send_unencrypted" />
</menu>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_button_context__send_textsecure_message"
android:id="@+id/menu_context_send_push" />
<item android:title="@string/conversation_button_context__send_unencrypted_sms"
android:id="@+id/menu_context_send_unencrypted_sms" />
</menu>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_button_context__send_textsecure_message"
android:id="@+id/menu_context_send_push" />
<item android:title="@string/conversation_button_context__send_encrypted_sms"
android:id="@+id/menu_context_send_encrypted_sms" />
<item android:title="@string/conversation_button_context__send_unencrypted_sms"
android:id="@+id/menu_context_send_unencrypted_sms" />
</menu>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_button_context__send_encrypted_sms"
android:id="@+id/menu_context_send_encrypted_sms" />
<item android:title="@string/conversation_button_context__send_unencrypted_sms"
android:id="@+id/menu_context_send_unencrypted_sms" />
</menu>

View File

@ -781,7 +781,9 @@
<string name="push_directory__menu_refresh">Refresh contact list</string>
<!-- conversation_button_context -->
<string name="conversation_button_context__menu_send_unencrypted">Send unencrypted</string>
<string name="conversation_button_context__send_textsecure_message">Send TextSecure message</string>
<string name="conversation_button_context__send_unencrypted_sms">Send unencrypted SMS</string>
<string name="conversation_button_context__send_encrypted_sms">Send encrypted SMS</string>
<!-- conversation_callable -->
<string name="conversation_callable__menu_call">Call</string>
@ -841,6 +843,7 @@
<!-- verify_keys -->
<string name="verify_keys__menu_verified">Verified</string>
<!-- EOF -->
</resources>

View File

@ -193,7 +193,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
@Override
protected void onResume() {
super.onResume();
dynamicTheme.onResume(this);
dynamicLanguage.onResume(this);
@ -312,16 +311,28 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if (isEncryptedConversation) {
android.view.MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.conversation_button_context, menu);
if (isEncryptedConversation && isSingleConversation()) {
boolean isPushDestination = DirectoryHelper.isPushDestination(this, getRecipients());
Recipient primaryRecipient = getRecipients() == null ? null : getRecipients().getPrimaryRecipient();
boolean hasSession = Session.hasSession(this, masterSecret, primaryRecipient);
int context;
if (isPushDestination && hasSession) context = R.menu.conversation_button_context_secure_push;
else if (isPushDestination) context = R.menu.conversation_button_context_insecure_push;
else if (hasSession) context = R.menu.conversation_button_context_secure_sms;
else return;
getMenuInflater().inflate(context, menu);
}
}
@Override
public boolean onContextItemSelected(android.view.MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_context_send_unencrypted: sendMessage(true); return true;
case R.id.menu_context_send_push: sendMessage(false, false); return true;
case R.id.menu_context_send_encrypted_sms: sendMessage(false, true); return true;
case R.id.menu_context_send_unencrypted_sms: sendMessage(true, true); return true;
}
return false;
@ -402,7 +413,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE"));
long allocatedThreadId = MessageSender.send(self, masterSecret,
endSessionMessage, threadId);
endSessionMessage, threadId, false);
sendComplete(recipients, allocatedThreadId, allocatedThreadId != self.threadId);
} else {
@ -444,7 +455,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(self, getRecipients(),
context, null);
MessageSender.send(self, masterSecret, outgoingMessage, threadId);
MessageSender.send(self, masterSecret, outgoingMessage, threadId, false);
DatabaseFactory.getGroupDatabase(self).remove(groupId, TextSecurePreferences.getLocalNumber(self));
initializeEnabledCheck();
} catch (IOException e) {
@ -1009,45 +1020,22 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
fragment.scrollToBottom();
}
private void sendMessage(boolean forcePlaintext) {
private void sendMessage(boolean forcePlaintext, boolean forceSms) {
try {
Recipients recipients = getRecipients();
if (recipients == null)
throw new RecipientFormattingException("Badly formatted");
String body = getMessage();
long allocatedThreadId;
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
handleManualMmsRequired();
return;
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
SlideDeck slideDeck;
if (attachmentManager.isAttachmentPresent()) slideDeck = attachmentManager.getSlideDeck();
else slideDeck = new SlideDeck();
OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(this, recipients, slideDeck,
body, distributionType);
if (isEncryptedConversation && !forcePlaintext) {
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessage);
}
allocatedThreadId = MessageSender.send(this, masterSecret, outgoingMessage, threadId);
allocatedThreadId = sendMediaMessage(forcePlaintext, forceSms);
} else {
OutgoingTextMessage message;
if (isEncryptedConversation && !forcePlaintext) {
message = new OutgoingEncryptedMessage(recipients, body);
} else {
message = new OutgoingTextMessage(recipients, body);
}
Log.w(TAG, "Sending message...");
allocatedThreadId = MessageSender.send(ConversationActivity.this, masterSecret,
message, threadId);
allocatedThreadId = sendTextMessage(forcePlaintext, forceSms);
}
sendComplete(recipients, allocatedThreadId, allocatedThreadId != this.threadId);
@ -1065,6 +1053,41 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
}
}
private long sendMediaMessage(boolean forcePlaintext, boolean forceSms)
throws InvalidMessageException, MmsException
{
SlideDeck slideDeck;
if (attachmentManager.isAttachmentPresent()) slideDeck = attachmentManager.getSlideDeck();
else slideDeck = new SlideDeck();
OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(this, recipients, slideDeck,
getMessage(), distributionType);
if (isEncryptedConversation && !forcePlaintext) {
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessage);
}
return MessageSender.send(this, masterSecret, outgoingMessage, threadId, forceSms);
}
private long sendTextMessage(boolean forcePlaintext, boolean forceSms)
throws InvalidMessageException
{
OutgoingTextMessage message;
if (isEncryptedConversation && !forcePlaintext) {
message = new OutgoingEncryptedMessage(recipients, getMessage());
} else {
message = new OutgoingTextMessage(recipients, getMessage());
}
Log.w(TAG, "Sending message...");
return MessageSender.send(ConversationActivity.this, masterSecret, message, threadId, forceSms);
}
// Listeners
private class AttachmentTypeListener implements DialogInterface.OnClickListener {
@ -1092,7 +1115,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
private class SendButtonListener implements OnClickListener, TextView.OnEditorActionListener {
@Override
public void onClick(View v) {
sendMessage(false);
sendMessage(false, false);
}
@Override

View File

@ -459,7 +459,7 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
.build();
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(this, groupRecipient, context, avatar);
long threadId = MessageSender.send(this, masterSecret, outgoingMessage, -1);
long threadId = MessageSender.send(this, masterSecret, outgoingMessage, -1, false);
return new Pair<Long, Recipients>(threadId, groupRecipient);
} catch (RecipientFormattingException e) {

View File

@ -77,7 +77,7 @@ public class KeyExchangeInitiator {
sessionRecordV2.getSessionState().setPendingKeyExchange(sequence, baseKey, ephemeralKey, identityKey);
sessionRecordV2.save();
MessageSender.send(context, masterSecret, textMessage, -1);
MessageSender.send(context, masterSecret, textMessage, -1, false);
}
private static boolean hasInitiatedSession(Context context, MasterSecret masterSecret,

View File

@ -206,7 +206,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
OutgoingKeyExchangeMessage textMessage = new OutgoingKeyExchangeMessage(recipient,
ourMessage.serialize());
MessageSender.send(context, masterSecret, textMessage, threadId);
MessageSender.send(context, masterSecret, textMessage, threadId, false);
}
if (message.getSequence() != sessionRecord.getSessionState().getPendingKeyExchangeSequence()) {

View File

@ -59,13 +59,13 @@ public class EncryptingSmsDatabase extends SmsDatabase {
}
public List<Long> insertMessageOutbox(MasterSecret masterSecret, long threadId,
OutgoingTextMessage message)
OutgoingTextMessage message, boolean forceSms)
{
long type = Types.BASE_OUTBOX_TYPE;
message = message.withBody(getEncryptedBody(masterSecret, message.getMessageBody()));
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
return insertMessageOutbox(threadId, message, type);
return insertMessageOutbox(threadId, message, type, forceSms);
}
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret,

View File

@ -572,14 +572,14 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
Trimmer.trimThread(context, threadId);
}
public long insertMessageOutbox(MasterSecret masterSecret, OutgoingMediaMessage message, long threadId)
public long insertMessageOutbox(MasterSecret masterSecret, OutgoingMediaMessage message,
long threadId, boolean forceSms)
throws MmsException
{
long type = Types.BASE_OUTBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
if (message.isSecure()) {
type |= Types.SECURE_MESSAGE_BIT;
}
if (message.isSecure()) type |= Types.SECURE_MESSAGE_BIT;
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
if (message.isGroup()) {
if (((OutgoingGroupMediaMessage)message).isGroupUpdate()) type |= Types.GROUP_UPDATE_BIT;

View File

@ -362,10 +362,13 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
return insertMessageInbox(message, Types.BASE_INBOX_TYPE);
}
protected List<Long> insertMessageOutbox(long threadId, OutgoingTextMessage message, long type) {
protected List<Long> insertMessageOutbox(long threadId, OutgoingTextMessage message,
long type, boolean forceSms)
{
if (message.isKeyExchange()) type |= Types.KEY_EXCHANGE_BIT;
else if (message.isSecureMessage()) type |= Types.SECURE_MESSAGE_BIT;
else if (message.isEndSession()) type |= Types.END_SESSION_BIT;
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
long date = System.currentTimeMillis();
List<Long> messageIds = new LinkedList<Long>();

View File

@ -32,14 +32,14 @@ import ws.com.google.android.mms.MmsException;
public class MessageSender {
public static long send(Context context, MasterSecret masterSecret,
OutgoingTextMessage message, long threadId)
OutgoingTextMessage message, long threadId,
boolean forceSms)
{
if (threadId == -1)
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(message.getRecipients());
List<Long> messageIds = DatabaseFactory.getEncryptingSmsDatabase(context)
.insertMessageOutbox(masterSecret, threadId, message);
.insertMessageOutbox(masterSecret, threadId, message, forceSms);
for (long messageId : messageIds) {
Log.w("SMSSender", "Got message id for new message: " + messageId);
@ -53,14 +53,16 @@ public class MessageSender {
return threadId;
}
public static long send(Context context, MasterSecret masterSecret, OutgoingMediaMessage message, long threadId)
public static long send(Context context, MasterSecret masterSecret,
OutgoingMediaMessage message,
long threadId, boolean forceSms)
throws MmsException
{
if (threadId == -1)
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(message.getRecipients(), message.getDistributionType());
long messageId = DatabaseFactory.getMmsDatabase(context)
.insertMessageOutbox(masterSecret, message, threadId);
.insertMessageOutbox(masterSecret, message, threadId, forceSms);
Intent intent = new Intent(SendReceiveService.SEND_MMS_ACTION, null,
context, SendReceiveService.class);