aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel@gultsch.de>2015-10-30 10:18:27 +0100
committerDaniel Gultsch <daniel@gultsch.de>2015-10-30 10:18:27 +0100
commit6a458b853ca5cdcc9ebe8237706899449701ca8c (patch)
treee6552d076b27a75cdc57ef602941e44df39b3c68
parent1ec3d86eb7cfb518957abce5b8c5cdb2b89866da (diff)
parent016a57f123dad15b4dabce320759f29155a150a5 (diff)
Merge pull request #1513 from fiaxh/pgp_background_decryption
PGP messages background decryption
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java162
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/PgpEngine.java19
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Account.java7
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Conversation.java1
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java10
-rw-r--r--src/main/java/eu/siacs/conversations/services/NotificationService.java2
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java15
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java6
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java138
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java6
-rw-r--r--src/main/res/values/strings.xml3
11 files changed, 294 insertions, 75 deletions
diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java
new file mode 100644
index 00000000..ed67dc65
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java
@@ -0,0 +1,162 @@
+package eu.siacs.conversations.crypto;
+
+import android.app.PendingIntent;
+
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.ui.UiCallback;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class PgpDecryptionService {
+
+ private final XmppConnectionService xmppConnectionService;
+ private final ConcurrentHashMap<String, List<Message>> messages = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<String, Boolean> decryptingMessages = new ConcurrentHashMap<>();
+ private Boolean keychainLocked = false;
+ private final Object keychainLockedLock = new Object();
+
+ public PgpDecryptionService(XmppConnectionService xmppConnectionService) {
+ this.xmppConnectionService = xmppConnectionService;
+ }
+
+ public void add(Message message) {
+ if (isRunning()) {
+ decryptDirectly(message);
+ } else {
+ store(message);
+ }
+ }
+
+ public void addAll(List<Message> messagesList) {
+ if (!messagesList.isEmpty()) {
+ String conversationUuid = messagesList.get(0).getConversation().getUuid();
+ if (!messages.containsKey(conversationUuid)) {
+ List<Message> list = Collections.synchronizedList(new LinkedList<Message>());
+ messages.put(conversationUuid, list);
+ }
+ synchronized (messages.get(conversationUuid)) {
+ messages.get(conversationUuid).addAll(messagesList);
+ }
+ decryptAllMessages();
+ }
+ }
+
+ public void onKeychainUnlocked() {
+ synchronized (keychainLockedLock) {
+ keychainLocked = false;
+ }
+ decryptAllMessages();
+ }
+
+ public void onKeychainLocked() {
+ synchronized (keychainLockedLock) {
+ keychainLocked = true;
+ }
+ xmppConnectionService.updateConversationUi();
+ }
+
+ public void onOpenPgpServiceBound() {
+ decryptAllMessages();
+ }
+
+ public boolean isRunning() {
+ synchronized (keychainLockedLock) {
+ return !keychainLocked;
+ }
+ }
+
+ private void store(Message message) {
+ if (messages.containsKey(message.getConversation().getUuid())) {
+ messages.get(message.getConversation().getUuid()).add(message);
+ } else {
+ List<Message> messageList = Collections.synchronizedList(new LinkedList<Message>());
+ messageList.add(message);
+ messages.put(message.getConversation().getUuid(), messageList);
+ }
+ }
+
+ private void decryptAllMessages() {
+ for (String uuid : messages.keySet()) {
+ decryptMessages(uuid);
+ }
+ }
+
+ private void decryptMessages(final String uuid) {
+ synchronized (decryptingMessages) {
+ Boolean decrypting = decryptingMessages.get(uuid);
+ if ((decrypting != null && !decrypting) || decrypting == null) {
+ decryptingMessages.put(uuid, true);
+ decryptMessage(uuid);
+ }
+ }
+ }
+
+ private void decryptMessage(final String uuid) {
+ Message message = null;
+ synchronized (messages.get(uuid)) {
+ while (!messages.get(uuid).isEmpty()) {
+ if (messages.get(uuid).get(0).getEncryption() == Message.ENCRYPTION_PGP) {
+ if (isRunning()) {
+ message = messages.get(uuid).remove(0);
+ }
+ break;
+ } else {
+ messages.get(uuid).remove(0);
+ }
+ }
+ if (message != null && xmppConnectionService.getPgpEngine() != null) {
+ xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
+
+ @Override
+ public void userInputRequried(PendingIntent pi, Message message) {
+ messages.get(uuid).add(0, message);
+ decryptingMessages.put(uuid, false);
+ }
+
+ @Override
+ public void success(Message message) {
+ xmppConnectionService.updateConversationUi();
+ decryptMessage(uuid);
+ }
+
+ @Override
+ public void error(int error, Message message) {
+ message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
+ xmppConnectionService.updateConversationUi();
+ decryptMessage(uuid);
+ }
+ });
+ } else {
+ decryptingMessages.put(uuid, false);
+ }
+ }
+ }
+
+ private void decryptDirectly(final Message message) {
+ if (message.getEncryption() == Message.ENCRYPTION_PGP && xmppConnectionService.getPgpEngine() != null) {
+ xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
+
+ @Override
+ public void userInputRequried(PendingIntent pi, Message message) {
+ store(message);
+ }
+
+ @Override
+ public void success(Message message) {
+ xmppConnectionService.updateConversationUi();
+ xmppConnectionService.getNotificationService().updateNotification(false);
+ }
+
+ @Override
+ public void error(int error, Message message) {
+ message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
+ xmppConnectionService.updateConversationUi();
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
index 8f8122f0..257d0f7e 100644
--- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
+++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
@@ -50,6 +50,7 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
+ notifyPgpDecryptionService(message.getContact().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@@ -64,6 +65,7 @@ public class PgpEngine {
&& manager.getAutoAcceptFileSize() > 0) {
manager.createNewDownloadConnection(message);
}
+ mXmppConnectionService.updateMessage(message);
callback.success(message);
}
} catch (IOException e) {
@@ -158,6 +160,7 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
+ notifyPgpDecryptionService(message.getContact().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@@ -203,6 +206,7 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
+ notifyPgpDecryptionService(message.getContact().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@@ -252,6 +256,7 @@ public class PgpEngine {
InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream();
Intent result = api.executeApi(params, is, os);
+ notifyPgpDecryptionService(account, OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@@ -282,6 +287,7 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
+ notifyPgpDecryptionService(account, OpenPgpApi.ACTION_SIGN, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
StringBuilder signatureBuilder = new StringBuilder();
@@ -368,4 +374,17 @@ public class PgpEngine {
return (PendingIntent) result
.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
}
+
+ private void notifyPgpDecryptionService(Account account, String action, final Intent result) {
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+ case OpenPgpApi.RESULT_CODE_SUCCESS:
+ if (OpenPgpApi.ACTION_SIGN.equals(action)) {
+ account.getPgpDecryptionService().onKeychainUnlocked();
+ }
+ break;
+ case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
+ account.getPgpDecryptionService().onKeychainLocked();
+ break;
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java
index c5791625..fbee5b8a 100644
--- a/src/main/java/eu/siacs/conversations/entities/Account.java
+++ b/src/main/java/eu/siacs/conversations/entities/Account.java
@@ -4,6 +4,7 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.os.SystemClock;
+import eu.siacs.conversations.crypto.PgpDecryptionService;
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
import net.java.otr4j.crypto.OtrCryptoException;
@@ -137,6 +138,7 @@ public class Account extends AbstractEntity {
protected boolean online = false;
private OtrService mOtrService = null;
private AxolotlService axolotlService = null;
+ private PgpDecryptionService pgpDecryptionService = null;
private XmppConnection xmppConnection = null;
private long mEndGracePeriod = 0L;
private String otrFingerprint;
@@ -313,12 +315,17 @@ public class Account extends AbstractEntity {
if (xmppConnection != null) {
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
}
+ this.pgpDecryptionService = new PgpDecryptionService(context);
}
public OtrService getOtrService() {
return this.mOtrService;
}
+ public PgpDecryptionService getPgpDecryptionService() {
+ return pgpDecryptionService;
+ }
+
public XmppConnection getXmppConnection() {
return this.xmppConnection;
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 5f3f1a6e..473ef0fe 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -777,6 +777,7 @@ public class Conversation extends AbstractEntity implements Blockable {
synchronized (this.messages) {
this.messages.addAll(index, messages);
}
+ account.getPgpDecryptionService().addAll(messages);
}
public void sort() {
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index 05c23593..58ca5135 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -3,6 +3,7 @@ package eu.siacs.conversations.parser;
import android.util.Log;
import android.util.Pair;
+import eu.siacs.conversations.crypto.PgpDecryptionService;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
@@ -114,6 +115,13 @@ public class MessageParser extends AbstractParser implements
return finishedMessage;
}
+ private Message parsePGPChat(final Conversation conversation, String pgpEncrypted, int status) {
+ final Message message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status);
+ PgpDecryptionService pgpDecryptionService = conversation.getAccount().getPgpDecryptionService();
+ pgpDecryptionService.add(message);
+ return message;
+ }
+
private class Invite {
Jid jid;
String password;
@@ -337,7 +345,7 @@ public class MessageParser extends AbstractParser implements
message = new Message(conversation, body, Message.ENCRYPTION_NONE, status);
}
} else if (pgpEncrypted != null) {
- message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status);
+ message = parsePGPChat(conversation, pgpEncrypted, status);
} else if (axolotlEncrypted != null) {
message = parseAxolotlChat(axolotlEncrypted, from, remoteMsgId, conversation, status);
if (message == null) {
diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java
index e9095020..125b1c26 100644
--- a/src/main/java/eu/siacs/conversations/services/NotificationService.java
+++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java
@@ -177,7 +177,7 @@ public class NotificationService {
mBuilder.setColor(mXmppConnectionService.getResources().getColor(R.color.primary));
}
- private void updateNotification(final boolean notify) {
+ public void updateNotification(final boolean notify) {
final NotificationManager notificationManager = (NotificationManager) mXmppConnectionService
.getSystemService(Context.NOTIFICATION_SERVICE);
final SharedPreferences preferences = mXmppConnectionService.getPreferences();
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 9f3527f1..9abacbd1 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -37,6 +37,7 @@ import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus;
+import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
@@ -659,7 +660,19 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
this.fileObserver.startWatching();
- this.pgpServiceConnection = new OpenPgpServiceConnection(getApplicationContext(), "org.sufficientlysecure.keychain");
+ this.pgpServiceConnection = new OpenPgpServiceConnection(getApplicationContext(), "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() {
+ @Override
+ public void onBound(IOpenPgpService service) {
+ for (Account account : accounts) {
+ if (account.getPgpDecryptionService() != null) {
+ account.getPgpDecryptionService().onOpenPgpServiceBound();
+ }
+ }
+ }
+
+ @Override
+ public void onError(Exception e) { }
+ });
this.pgpServiceConnection.bindToService();
this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 8bd51214..1345ada5 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -1194,8 +1194,7 @@ public class ConversationActivity extends XmppActivity
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_DECRYPT_PGP) {
- mConversationFragment.hideSnackbar();
- mConversationFragment.updateMessages();
+ mConversationFragment.onActivityResult(requestCode, resultCode, data);
} else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) {
mPendingImageUris.clear();
mPendingImageUris.addAll(extractUriFromIntent(data));
@@ -1240,6 +1239,9 @@ public class ConversationActivity extends XmppActivity
} else {
mPendingImageUris.clear();
mPendingFileUris.clear();
+ if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
+ mConversationFragment.onActivityResult(requestCode, resultCode, data);
+ }
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 05d6e5ee..7b83c2be 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -11,6 +11,7 @@ import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
+import android.support.annotation.Nullable;
import android.text.InputType;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -199,21 +200,47 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
};
- private IntentSender askForPassphraseIntent = null;
+ private final int KEYCHAIN_UNLOCK_NOT_REQUIRED = 0;
+ private final int KEYCHAIN_UNLOCK_REQUIRED = 1;
+ private final int KEYCHAIN_UNLOCK_PENDING = 2;
+ private int keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
protected OnClickListener clickToDecryptListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (activity.hasPgp() && askForPassphraseIntent != null) {
- try {
- getActivity().startIntentSenderForResult(
- askForPassphraseIntent,
- ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
- 0, 0);
- askForPassphraseIntent = null;
- } catch (SendIntentException e) {
- //
+ if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED
+ && activity.hasPgp() && !conversation.getAccount().getPgpDecryptionService().isRunning()) {
+ keychainUnlock = KEYCHAIN_UNLOCK_PENDING;
+ updateSnackBar(conversation);
+ Message message = getLastPgpDecryptableMessage();
+ if (message != null) {
+ activity.xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() {
+ @Override
+ public void success(Message object) {
+ conversation.getAccount().getPgpDecryptionService().onKeychainUnlocked();
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ }
+
+ @Override
+ public void error(int errorCode, Message object) {
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ }
+
+ @Override
+ public void userInputRequried(PendingIntent pi, Message object) {
+ try {
+ activity.startIntentSenderForResult(pi.getIntentSender(),
+ ConversationActivity.REQUEST_DECRYPT_PGP, null, 0, 0, 0);
+ } catch (SendIntentException e) {
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ updatePgpMessages();
+ }
+ }
+ });
}
+ } else {
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ updatePgpMessages();
}
}
};
@@ -224,8 +251,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
activity.verifyOtrSessionDialog(conversation, v);
}
};
- private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<>();
- private boolean mDecryptJobRunning = false;
private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
@Override
@@ -629,7 +654,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void onStop() {
- mDecryptJobRunning = false;
super.onStop();
if (this.conversation != null) {
final String msg = mEditMessage.getText().toString();
@@ -661,10 +685,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
this.conversation.trim();
}
- this.askForPassphraseIntent = null;
+ this.keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
this.conversation = conversation;
- this.mDecryptJobRunning = false;
- this.mEncryptedMessages.clear();
if (this.conversation.getMode() == Conversation.MODE_MULTI) {
this.conversation.setNextCounterpart(null);
}
@@ -767,7 +789,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
default:
break;
}
- } else if (askForPassphraseIntent != null) {
+ } else if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED) {
showSnackbar(R.string.openpgp_messages_found, R.string.decrypt, clickToDecryptListener);
} else if (mode == Conversation.MODE_SINGLE
&& conversation.smpRequested()) {
@@ -791,19 +813,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
final ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
- updateSnackBar(this.conversation);
conversation.populateWithMessages(ConversationFragment.this.messageList);
- for (final Message message : this.messageList) {
- if (message.getEncryption() == Message.ENCRYPTION_PGP
- && (message.getStatus() == Message.STATUS_RECEIVED || message
- .getStatus() >= Message.STATUS_SEND)
- && message.getTransferable() == null) {
- if (!mEncryptedMessages.contains(message)) {
- mEncryptedMessages.add(message);
- }
- }
- }
- decryptNext();
+ updatePgpMessages();
+ updateSnackBar(conversation);
updateStatusMessages();
this.messageListAdapter.notifyDataSetChanged();
updateChatMsgHint();
@@ -815,46 +827,27 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
- private void decryptNext() {
- Message next = this.mEncryptedMessages.peek();
- PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
-
- if (next != null && engine != null && !mDecryptJobRunning) {
- mDecryptJobRunning = true;
- engine.decrypt(next, new UiCallback<Message>() {
-
- @Override
- public void userInputRequried(PendingIntent pi, Message message) {
- mDecryptJobRunning = false;
- askForPassphraseIntent = pi.getIntentSender();
- updateSnackBar(conversation);
- }
-
- @Override
- public void success(Message message) {
- mDecryptJobRunning = false;
- try {
- mEncryptedMessages.remove();
- } catch (final NoSuchElementException ignored) {
-
- }
- askForPassphraseIntent = null;
- activity.xmppConnectionService.updateMessage(message);
- }
-
- @Override
- public void error(int error, Message message) {
- message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
- mDecryptJobRunning = false;
- try {
- mEncryptedMessages.remove();
- } catch (final NoSuchElementException ignored) {
+ public void updatePgpMessages() {
+ if (keychainUnlock != KEYCHAIN_UNLOCK_PENDING) {
+ if (getLastPgpDecryptableMessage() != null
+ && !conversation.getAccount().getPgpDecryptionService().isRunning()) {
+ keychainUnlock = KEYCHAIN_UNLOCK_REQUIRED;
+ } else {
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ }
+ }
+ }
- }
- activity.refreshUi();
- }
- });
+ @Nullable
+ private Message getLastPgpDecryptableMessage() {
+ for (final Message message : this.messageList) {
+ if (message.getEncryption() == Message.ENCRYPTION_PGP
+ && (message.getStatus() == Message.STATUS_RECEIVED || message.getStatus() >= Message.STATUS_SEND)
+ && message.getTransferable() == null) {
+ return message;
+ }
}
+ return null;
}
private void messageSent() {
@@ -1274,7 +1267,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public void onActivityResult(int requestCode, int resultCode,
final Intent data) {
if (resultCode == Activity.RESULT_OK) {
- if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) {
+ if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
+ activity.getSelectedConversation().getAccount().getPgpDecryptionService().onKeychainUnlocked();
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ updatePgpMessages();
+ } else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) {
final String body = mEditMessage.getText().toString();
Message message = new Message(conversation, body, conversation.getNextEncryption());
sendAxolotlMessage(message);
@@ -1282,6 +1279,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
int choice = data.getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID);
activity.selectPresenceToAttachFile(choice, conversation.getNextEncryption());
}
+ } else {
+ if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
+ keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
+ updatePgpMessages();
+ }
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index 2befd65c..019b83d3 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -550,7 +550,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
if (activity.hasPgp()) {
- displayInfoMessage(viewHolder,activity.getString(R.string.encrypted_message),darkBackground);
+ if (account.getPgpDecryptionService().isRunning()) {
+ displayInfoMessage(viewHolder, activity.getString(R.string.message_decrypting), darkBackground);
+ } else {
+ displayInfoMessage(viewHolder, activity.getString(R.string.pgp_message), darkBackground);
+ }
} else {
displayInfoMessage(viewHolder,activity.getString(R.string.install_openkeychain),darkBackground);
if (viewHolder != null) {
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index c4ba759b..7ed0d386 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -30,7 +30,8 @@
<string name="minutes_ago">%d mins ago</string>
<string name="unread_conversations">unread Conversations</string>
<string name="sending">sending…</string>
- <string name="encrypted_message">Decrypting message. Please wait…</string>
+ <string name="message_decrypting">Decrypting message. Please wait…</string>
+ <string name="pgp_message">OpenPGP encrypted message</string>
<string name="nick_in_use">Nickname is already in use</string>
<string name="admin">Admin</string>
<string name="owner">Owner</string>