improved 'next encryption' selection

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          | 63 
src/main/java/eu/siacs/conversations/entities/Message.java               |  2 
src/main/java/eu/siacs/conversations/parser/MessageParser.java           |  2 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 20 
src/main/java/eu/siacs/conversations/ui/ConversationActivity.java        | 23 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java        | 32 
6 files changed, 69 insertions(+), 73 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -549,42 +549,51 @@ public class Conversation extends AbstractEntity implements Blockable {
 		return this.nextCounterpart;
 	}
 
-	public int getLatestEncryption() {
-		int latestEncryption = this.getLatestMessage().getEncryption();
-		if ((latestEncryption == Message.ENCRYPTION_DECRYPTED)
-				|| (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) {
-			return Message.ENCRYPTION_PGP;
-		} else {
-			return latestEncryption;
+	private int getMostRecentlyUsedOutgoingEncryption() {
+		synchronized (this.messages) {
+			for(int i = this.messages.size() -1; i >= 0; --i) {
+				final Message m = this.messages.get(0);
+				if (!m.isCarbon() && m.getStatus() != Message.STATUS_RECEIVED) {
+					final int e = m.getEncryption();
+					if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) {
+						return Message.ENCRYPTION_PGP;
+					} else {
+						return e;
+					}
+				}
+			}
 		}
+		return Message.ENCRYPTION_NONE;
 	}
 
-	public int getNextEncryption(boolean force) {
-		int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1);
-		if (next == -1) {
-			int latest = this.getLatestEncryption();
-			if (latest == Message.ENCRYPTION_NONE) {
-				if (force && getMode() == MODE_SINGLE) {
-					return Message.ENCRYPTION_OTR;
-				} else if (getContact().getPresences().size() == 1) {
-					if (getContact().getOtrFingerprints().size() >= 1) {
-						return Message.ENCRYPTION_OTR;
+	private int getMostRecentlyUsedIncomingEncryption() {
+		synchronized (this.messages) {
+			for(int i = this.messages.size() -1; i >= 0; --i) {
+				final Message m = this.messages.get(0);
+				if (m.getStatus() == Message.STATUS_RECEIVED) {
+					final int e = m.getEncryption();
+					if (e == Message.ENCRYPTION_DECRYPTED || e == Message.ENCRYPTION_DECRYPTION_FAILED) {
+						return Message.ENCRYPTION_PGP;
 					} else {
-						return latest;
+						return e;
 					}
-				} else {
-					return latest;
 				}
-			} else {
-				return latest;
 			}
 		}
-		if (next == Message.ENCRYPTION_NONE && force
-				&& getMode() == MODE_SINGLE) {
-			return Message.ENCRYPTION_OTR;
-		} else {
-			return next;
+		return Message.ENCRYPTION_NONE;
+	}
+
+	public int getNextEncryption() {
+		int next = this.getIntAttribute(ATTRIBUTE_NEXT_ENCRYPTION, -1);
+		if (next == -1) {
+			int outgoing = this.getMostRecentlyUsedOutgoingEncryption();
+			if (outgoing == Message.ENCRYPTION_NONE) {
+				return this.getMostRecentlyUsedIncomingEncryption();
+			} else {
+				return outgoing;
+			}
 		}
+		return next;
 	}
 
 	public void setNextEncryption(int encryption) {

src/main/java/eu/siacs/conversations/parser/MessageParser.java 🔗

@@ -73,11 +73,9 @@ public class MessageParser extends AbstractParser implements
 			body = otrSession.transformReceiving(body);
 			SessionStatus status = otrSession.getSessionStatus();
 			if (body == null && status == SessionStatus.ENCRYPTED) {
-				conversation.setNextEncryption(Message.ENCRYPTION_OTR);
 				mXmppConnectionService.onOtrSessionEstablished(conversation);
 				return null;
 			} else if (body == null && status == SessionStatus.FINISHED) {
-				conversation.setNextEncryption(Message.ENCRYPTION_NONE);
 				conversation.resetOtrSession();
 				mXmppConnectionService.updateConversationUi();
 				return null;

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -349,7 +349,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	public void attachLocationToConversation(final Conversation conversation,
 											 final Uri uri,
 											 final UiCallback<Message> callback) {
-		int encryption = conversation.getNextEncryption(forceEncryption());
+		int encryption = conversation.getNextEncryption();
 		if (encryption == Message.ENCRYPTION_PGP) {
 			encryption = Message.ENCRYPTION_DECRYPTED;
 		}
@@ -368,12 +368,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 			final Uri uri,
 			final UiCallback<Message> callback) {
 		final Message message;
-		if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
-			message = new Message(conversation, "",
-					Message.ENCRYPTION_DECRYPTED);
+		if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
+			message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
 		} else {
-			message = new Message(conversation, "",
-					conversation.getNextEncryption(forceEncryption()));
+			message = new Message(conversation, "", conversation.getNextEncryption());
 		}
 		message.setCounterpart(conversation.getNextCounterpart());
 		message.setType(Message.TYPE_FILE);
@@ -409,12 +407,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	public void attachImageToConversation(final Conversation conversation,
 			final Uri uri, final UiCallback<Message> callback) {
 		final Message message;
-		if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
-			message = new Message(conversation, "",
-					Message.ENCRYPTION_DECRYPTED);
+		if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
+			message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
 		} else {
-			message = new Message(conversation, "",
-					conversation.getNextEncryption(forceEncryption()));
+			message = new Message(conversation, "",conversation.getNextEncryption());
 		}
 		message.setCounterpart(conversation.getNextCounterpart());
 		message.setType(Message.TYPE_IMAGE);
@@ -424,7 +420,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 			public void run() {
 				try {
 					getFileBackend().copyImageToPrivateStorage(message, uri);
-					if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) {
+					if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
 						getPgpEngine().encrypt(message, callback);
 					} else {
 						callback.success(message);

src/main/java/eu/siacs/conversations/ui/ConversationActivity.java 🔗

@@ -385,7 +385,7 @@ public class ConversationActivity extends XmppActivity
 		} else {
 			menuAdd.setVisible(!isConversationsOverviewHideable());
 			if (this.getSelectedConversation() != null) {
-				if (this.getSelectedConversation().getNextEncryption(forceEncryption()) != Message.ENCRYPTION_NONE) {
+				if (this.getSelectedConversation().getNextEncryption() != Message.ENCRYPTION_NONE) {
 					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 						menuSecure.setIcon(R.drawable.ic_lock_white_24dp);
 					} else {
@@ -498,7 +498,7 @@ public class ConversationActivity extends XmppActivity
 				break;
 		}
 		final Conversation conversation = getSelectedConversation();
-		final int encryption = conversation.getNextEncryption(forceEncryption());
+		final int encryption = conversation.getNextEncryption();
 		if (encryption == Message.ENCRYPTION_PGP) {
 			if (hasPgp()) {
 				if (conversation.getContact().getPgpKeyId() != 0) {
@@ -787,15 +787,10 @@ public class ConversationActivity extends XmppActivity
 			if (conversation.getMode() == Conversation.MODE_MULTI) {
 				otr.setEnabled(false);
 				axolotl.setEnabled(false);
-			} else {
-				if (forceEncryption()) {
-					none.setVisible(false);
-				}
-			}
-			if (!conversation.getAccount().getAxolotlService().isContactAxolotlCapable(conversation.getContact())) {
+			} else if (!conversation.getAccount().getAxolotlService().isContactAxolotlCapable(conversation.getContact())) {
 				axolotl.setEnabled(false);
 			}
-			switch (conversation.getNextEncryption(forceEncryption())) {
+			switch (conversation.getNextEncryption()) {
 				case Message.ENCRYPTION_NONE:
 					none.setChecked(true);
 					break;
@@ -806,8 +801,7 @@ public class ConversationActivity extends XmppActivity
 					pgp.setChecked(true);
 					break;
 				case Message.ENCRYPTION_AXOLOTL:
-					popup.getMenu().findItem(R.id.encryption_choice_axolotl)
-							.setChecked(true);
+					axolotl.setChecked(true);
 					break;
 				default:
 					none.setChecked(true);
@@ -820,8 +814,7 @@ public class ConversationActivity extends XmppActivity
 	protected void muteConversationDialog(final Conversation conversation) {
 		AlertDialog.Builder builder = new AlertDialog.Builder(this);
 		builder.setTitle(R.string.disable_notifications);
-		final int[] durations = getResources().getIntArray(
-				R.array.mute_options_durations);
+		final int[] durations = getResources().getIntArray(R.array.mute_options_durations);
 		builder.setItems(R.array.mute_options_descriptions,
 				new OnClickListener() {
 
@@ -1253,10 +1246,6 @@ public class ConversationActivity extends XmppActivity
 				});
 	}
 
-	public boolean forceEncryption() {
-		return getPreferences().getBoolean("force_encryption", false);
-	}
-
 	public boolean useSendButtonToIndicateStatus() {
 		return getPreferences().getBoolean("send_button_status", false);
 	}

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -293,23 +293,27 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 		if (body.length() == 0 || this.conversation == null) {
 			return;
 		}
-		Message message = new Message(conversation, body, conversation.getNextEncryption(activity.forceEncryption()));
+		Message message = new Message(conversation, body, conversation.getNextEncryption());
 		if (conversation.getMode() == Conversation.MODE_MULTI) {
 			if (conversation.getNextCounterpart() != null) {
 				message.setCounterpart(conversation.getNextCounterpart());
 				message.setType(Message.TYPE_PRIVATE);
 			}
 		}
-		if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_OTR) {
-			sendOtrMessage(message);
-		} else if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_PGP) {
-			sendPgpMessage(message);
-		} else if (conversation.getNextEncryption(activity.forceEncryption()) == Message.ENCRYPTION_AXOLOTL) {
-			if(!activity.trustKeysIfNeeded(ConversationActivity.REQUEST_TRUST_KEYS_TEXT)) {
-				sendAxolotlMessage(message);
-			}
-		} else {
-			sendPlainTextMessage(message);
+		switch (conversation.getNextEncryption()) {
+			case Message.ENCRYPTION_OTR:
+				sendOtrMessage(message);
+				break;
+			case Message.ENCRYPTION_PGP:
+				sendPgpMessage(message);
+				break;
+			case Message.ENCRYPTION_AXOLOTL:
+				if(!activity.trustKeysIfNeeded(ConversationActivity.REQUEST_TRUST_KEYS_TEXT)) {
+					sendAxolotlMessage(message);
+				}
+				break;
+			default:
+				sendPlainTextMessage(message);
 		}
 	}
 
@@ -320,7 +324,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 					R.string.send_private_message_to,
 					conversation.getNextCounterpart().getResourcepart()));
 		} else {
-			switch (conversation.getNextEncryption(activity.forceEncryption())) {
+			switch (conversation.getNextEncryption()) {
 				case Message.ENCRYPTION_NONE:
 					mEditMessage
 							.setHint(getString(R.string.send_plain_text_message));
@@ -1211,11 +1215,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 		if (resultCode == Activity.RESULT_OK) {
 			if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) {
 				final String body = mEditMessage.getText().toString();
-				Message message = new Message(conversation, body, conversation.getNextEncryption(activity.forceEncryption()));
+				Message message = new Message(conversation, body, conversation.getNextEncryption());
 				sendAxolotlMessage(message);
 			} else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_MENU) {
 				int choice = data.getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID);
-				activity.selectPresenceToAttachFile(choice, conversation.getNextEncryption(activity.forceEncryption()));
+				activity.selectPresenceToAttachFile(choice, conversation.getNextEncryption());
 			}
 		}
 	}