refactored pgp decryption

This commit is contained in:
Daniel Gultsch 2016-06-13 13:32:14 +02:00
parent 490a1ca3cf
commit 587fb3cca3
11 changed files with 207 additions and 336 deletions

View file

@ -1,162 +1,181 @@
package eu.siacs.conversations.crypto;
import android.app.PendingIntent;
import android.content.Intent;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.UiCallback;
import org.openintents.openpgp.util.OpenPgpApi;
import java.util.Collections;
import java.util.LinkedList;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.services.XmppConnectionService;
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();
private final XmppConnectionService mXmppConnectionService;
private OpenPgpApi openPgpApi = null;
public PgpDecryptionService(XmppConnectionService xmppConnectionService) {
this.xmppConnectionService = xmppConnectionService;
protected final ArrayDeque<Message> messages = new ArrayDeque();
Message currentMessage;
private PendingIntent pendingIntent;
public PgpDecryptionService(XmppConnectionService service) {
this.mXmppConnectionService = service;
}
public synchronized void decrypt(final Message message) {
messages.add(message);
continueDecryption();
}
public void add(Message message) {
if (isRunning()) {
decryptDirectly(message);
} else {
store(message);
public synchronized void decrypt(final List<Message> list) {
for(Message message : list) {
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
messages.add(message);
}
}
continueDecryption();
}
protected synchronized void decryptNext() {
if (pendingIntent == null
&& getOpenPgpApi() != null
&& (currentMessage = messages.poll()) != null) {
new Thread(new Runnable() {
@Override
public void run() {
executeApi(currentMessage);
decryptNext();
}
}).start();
}
}
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 synchronized void continueDecryption(boolean resetPending) {
if (resetPending) {
this.pendingIntent = null;
}
continueDecryption();
}
public void onKeychainUnlocked() {
synchronized (keychainLockedLock) {
keychainLocked = false;
}
decryptAllMessages();
}
public synchronized void continueDecryption() {
if (currentMessage == null) {
decryptNext();
}
}
public void onKeychainLocked() {
synchronized (keychainLockedLock) {
keychainLocked = true;
}
xmppConnectionService.updateConversationUi();
}
private synchronized OpenPgpApi getOpenPgpApi() {
if (openPgpApi == null) {
this.openPgpApi = mXmppConnectionService.getOpenPgpApi();
}
return this.openPgpApi;
}
public void onOpenPgpServiceBound() {
decryptAllMessages();
}
private void executeApi(Message message) {
Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
if (message.getType() == Message.TYPE_TEXT) {
InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
final OutputStream os = new ByteArrayOutputStream();
Intent result = getOpenPgpApi().executeApi(params, is, os);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
try {
os.flush();
message.setBody(os.toString());
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
if (message.trusted()
&& message.treatAsDownloadable() != Message.Decision.NEVER
&& manager.getAutoAcceptFileSize() > 0) {
manager.createNewDownloadConnection(message);
}
} catch (IOException e) {
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
}
mXmppConnectionService.updateMessage(message);
break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
messages.addFirst(message);
currentMessage = null;
storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
break;
case OpenPgpApi.RESULT_CODE_ERROR:
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
mXmppConnectionService.updateMessage(message);
break;
}
} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
try {
final DownloadableFile inputFile = mXmppConnectionService.getFileBackend().getFile(message, false);
final DownloadableFile outputFile = mXmppConnectionService.getFileBackend().getFile(message, true);
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
InputStream is = new FileInputStream(inputFile);
OutputStream os = new FileOutputStream(outputFile);
Intent result = getOpenPgpApi().executeApi(params, is, os);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
URL url = message.getFileParams().url;
mXmppConnectionService.getFileBackend().updateFileParams(message,url);
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
inputFile.delete();
mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile);
mXmppConnectionService.updateMessage(message);
break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
messages.addFirst(message);
currentMessage = null;
storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
break;
case OpenPgpApi.RESULT_CODE_ERROR:
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
mXmppConnectionService.updateMessage(message);
break;
}
} catch (final IOException e) {
message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED);
mXmppConnectionService.updateMessage(message);
}
}
}
public boolean isRunning() {
synchronized (keychainLockedLock) {
return !keychainLocked;
}
}
private void storePendingIntent(PendingIntent pendingIntent) {
this.pendingIntent = pendingIntent;
mXmppConnectionService.updateConversationUi();
}
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);
}
}
public synchronized boolean hasPendingIntent(Conversation conversation) {
if (pendingIntent == null) {
return false;
} else {
for(Message message : messages) {
if (message.getConversation() == conversation) {
return true;
}
}
return false;
}
}
private void decryptAllMessages() {
for (String uuid : messages.keySet()) {
decryptMessages(uuid);
}
}
public PendingIntent getPendingIntent() {
return pendingIntent;
}
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();
}
});
}
}
public boolean isConnected() {
return getOpenPgpApi() != null;
}
}

View file

@ -38,96 +38,6 @@ public class PgpEngine {
this.mXmppConnectionService = service;
}
public void decrypt(final Message message, final UiCallback<Message> callback) {
Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
final String uuid = message.getUuid();
if (message.getType() == Message.TYPE_TEXT) {
InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
final OutputStream os = new ByteArrayOutputStream();
api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
@Override
public void onReturn(Intent result) {
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
try {
os.flush();
if (message.getEncryption() == Message.ENCRYPTION_PGP
&& message.getUuid().equals(uuid)) {
message.setBody(os.toString());
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
if (message.trusted()
&& message.treatAsDownloadable() != Message.Decision.NEVER
&& manager.getAutoAcceptFileSize() > 0) {
manager.createNewDownloadConnection(message);
}
mXmppConnectionService.updateMessage(message);
callback.success(message);
}
} catch (IOException e) {
callback.error(R.string.openpgp_error, message);
return;
}
return;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
callback.userInputRequried((PendingIntent) result
.getParcelableExtra(OpenPgpApi.RESULT_INTENT),
message);
return;
case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, message);
}
}
});
} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
try {
final DownloadableFile inputFile = this.mXmppConnectionService
.getFileBackend().getFile(message, false);
final DownloadableFile outputFile = this.mXmppConnectionService
.getFileBackend().getFile(message, true);
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
InputStream is = new FileInputStream(inputFile);
OutputStream os = new FileOutputStream(outputFile);
api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
@Override
public void onReturn(Intent result) {
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
URL url = message.getFileParams().url;
mXmppConnectionService.getFileBackend().updateFileParams(message,url);
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
PgpEngine.this.mXmppConnectionService
.updateMessage(message);
inputFile.delete();
mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile);
callback.success(message);
return;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
callback.userInputRequried(
(PendingIntent) result
.getParcelableExtra(OpenPgpApi.RESULT_INTENT),
message);
return;
case OpenPgpApi.RESULT_CODE_ERROR:
callback.error(R.string.openpgp_error, message);
}
}
});
} catch (final IOException e) {
callback.error(R.string.error_decrypting_file, message);
}
}
}
public void encrypt(final Message message, final UiCallback<Message> callback) {
Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_ENCRYPT);
@ -156,7 +66,6 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@ -202,7 +111,6 @@ public class PgpEngine {
@Override
public void onReturn(Intent result) {
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_ENCRYPT, result);
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
@ -257,7 +165,6 @@ 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:
@ -315,7 +222,6 @@ 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();
@ -397,17 +303,4 @@ 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;
}
}
}

View file

@ -6,6 +6,7 @@ import android.os.SystemClock;
import android.util.Pair;
import eu.siacs.conversations.crypto.PgpDecryptionService;
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
import net.java.otr4j.crypto.OtrCryptoException;
@ -20,7 +21,6 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.OtrService;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@ -83,6 +83,14 @@ public class Account extends AbstractEntity {
return getRoster().getContact(jid);
}
public boolean hasPendingPgpIntent(Conversation conversation) {
return pgpDecryptionService != null && pgpDecryptionService.hasPendingIntent(conversation);
}
public boolean isPgpDecryptionServiceConnected() {
return pgpDecryptionService != null && pgpDecryptionService.isConnected();
}
public enum State {
DISABLED,
OFFLINE,
@ -398,10 +406,10 @@ public class Account extends AbstractEntity {
public void initAccountServices(final XmppConnectionService context) {
this.mOtrService = new OtrService(context, this);
this.axolotlService = new AxolotlService(this, context);
this.pgpDecryptionService = new PgpDecryptionService(context);
if (xmppConnection != null) {
xmppConnection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService);
}
this.pgpDecryptionService = new PgpDecryptionService(context);
}
public OtrService getOtrService() {
@ -409,7 +417,7 @@ public class Account extends AbstractEntity {
}
public PgpDecryptionService getPgpDecryptionService() {
return pgpDecryptionService;
return this.pgpDecryptionService;
}
public XmppConnection getXmppConnection() {

View file

@ -932,7 +932,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
synchronized (this.messages) {
this.messages.addAll(index, messages);
}
account.getPgpDecryptionService().addAll(messages);
account.getPgpDecryptionService().decrypt(messages);
}
public void sort() {

View file

@ -127,7 +127,7 @@ public class HttpDownloadConnection implements Transferable {
message.setTransferable(null);
mHttpConnectionManager.finishConnection(this);
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
message.getConversation().getAccount().getPgpDecryptionService().add(message);
message.getConversation().getAccount().getPgpDecryptionService().decrypt(message);
}
mXmppConnectionService.updateConversationUi();
if (acceptedAutomatically) {

View file

@ -7,7 +7,6 @@ import android.util.Pair;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@ -32,7 +31,6 @@ import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.Xmlns;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
@ -484,7 +482,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
sendMessageReceipts(account, packet);
}
if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) {
conversation.getAccount().getPgpDecryptionService().add(replacedMessage);
conversation.getAccount().getPgpDecryptionService().decrypt(replacedMessage);
}
return;
} else {
@ -508,7 +506,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
conversation.getAccount().getPgpDecryptionService().add(message);
conversation.getAccount().getPgpDecryptionService().decrypt(message);
}
if (query == null || query.getWith() == null) { //either no mam or catchup

View file

@ -49,7 +49,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@ -62,6 +61,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import de.duenndns.ssl.MemorizingTrustManager;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpDecryptionService;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
@ -383,6 +383,16 @@ public class XmppConnectionService extends Service {
}
public OpenPgpApi getOpenPgpApi() {
if (!Config.supportOpenPgp()) {
return null;
} else if (pgpServiceConnection != null && pgpServiceConnection.isBound()) {
return new OpenPgpApi(this, pgpServiceConnection.getService());
} else {
return null;
}
}
public FileBackend getFileBackend() {
return this.fileBackend;
}
@ -754,8 +764,9 @@ public class XmppConnectionService extends Service {
@Override
public void onBound(IOpenPgpService2 service) {
for (Account account : accounts) {
if (account.getPgpDecryptionService() != null) {
account.getPgpDecryptionService().onOpenPgpServiceBound();
final PgpDecryptionService pgp = account.getPgpDecryptionService();
if(pgp != null) {
pgp.continueDecryption(true);
}
}
}

View file

@ -9,12 +9,9 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
@ -214,49 +211,25 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
return -1;
}
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 (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();
}
}
});
PendingIntent pendingIntent = conversation.getAccount().getPgpDecryptionService().getPendingIntent();
if (pendingIntent != null) {
try {
activity.startIntentSenderForResult(pendingIntent.getIntentSender(),
ConversationActivity.REQUEST_DECRYPT_PGP,
null,
0,
0,
0);
} catch (SendIntentException e) {
Toast.makeText(activity,R.string.unable_to_connect_to_keychain, Toast.LENGTH_SHORT).show();
conversation.getAccount().getPgpDecryptionService().continueDecryption(true);
}
} else {
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
updatePgpMessages();
}
updateSnackBar(conversation);
}
};
protected OnClickListener clickToVerify = new OnClickListener() {
@ -722,7 +695,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
message.setEncryption(Message.ENCRYPTION_PGP);
activity.updateConversationList();
updateMessages();
conversation.getAccount().getPgpDecryptionService().add(message);
conversation.getAccount().getPgpDecryptionService().decrypt(message);
}
protected void privateMessageWith(final Jid counterpart) {
@ -789,7 +762,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
this.conversation.trim();
}
this.keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
this.conversation = conversation;
boolean canWrite = this.conversation.getMode() == Conversation.MODE_SINGLE || this.conversation.getMucOptions().participating();
this.mEditMessage.setEnabled(canWrite);
@ -909,7 +881,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
default:
break;
}
} else if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED) {
} else if (account.hasPendingPgpIntent(conversation)) {
showSnackbar(R.string.openpgp_messages_found, R.string.decrypt, clickToDecryptListener);
} else if (mode == Conversation.MODE_SINGLE
&& conversation.smpRequested()) {
@ -932,7 +904,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
final ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
conversation.populateWithMessages(ConversationFragment.this.messageList);
updatePgpMessages();
updateSnackBar(conversation);
updateStatusMessages();
this.messageListAdapter.notifyDataSetChanged();
@ -945,29 +916,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
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;
}
}
}
@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() {
mEditMessage.setText("");
updateChatMsgHint();
@ -1424,9 +1372,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
final Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
activity.getSelectedConversation().getAccount().getPgpDecryptionService().onKeychainUnlocked();
keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED;
updatePgpMessages();
activity.getSelectedConversation().getAccount().getPgpDecryptionService().continueDecryption(true);
} else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) {
final String body = mEditMessage.getText().toString();
Message message = new Message(conversation, body, conversation.getNextEncryption());
@ -1435,11 +1381,6 @@ 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();
}
}
}

View file

@ -631,8 +631,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
displayOpenableMessage(viewHolder, message);
}
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
if (activity.hasPgp()) {
if (account.getPgpDecryptionService().isRunning()) {
if (account.isPgpDecryptionServiceConnected()) {
if (!account.hasPendingPgpIntent(conversation)) {
displayInfoMessage(viewHolder, activity.getString(R.string.message_decrypting), darkBackground);
} else {
displayInfoMessage(viewHolder, activity.getString(R.string.pgp_message), darkBackground);

View file

@ -110,7 +110,7 @@ public class JingleConnection implements Transferable {
if (message.getEncryption() != Message.ENCRYPTION_PGP) {
mXmppConnectionService.getFileBackend().updateMediaScanner(file);
} else {
account.getPgpDecryptionService().add(message);
account.getPgpDecryptionService().decrypt(message);
}
}

View file

@ -662,4 +662,5 @@
<string name="pref_theme_dark">Dark theme</string>
<string name="pref_use_green_background">Green Background</string>
<string name="pref_use_green_background_summary">Use green background for received messages</string>
<string name="unable_to_connect_to_keychain">Unable to connect to OpenKeychain</string>
</resources>