converge threads after decryption, and handle PendingIntents

This commit is contained in:
Vincent Breitmoser 2015-01-29 12:57:04 +01:00
parent bcd570f884
commit 1046308a38
3 changed files with 83 additions and 41 deletions

View File

@ -51,7 +51,6 @@ import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.SearchCondition; import com.fsck.k9.search.SearchSpecification.SearchCondition;
import com.fsck.k9.search.SearchSpecification.Searchfield; import com.fsck.k9.search.SearchSpecification.Searchfield;
import com.fsck.k9.view.MessageHeader; import com.fsck.k9.view.MessageHeader;
import com.fsck.k9.ui.messageview.MessageOpenPgpViewOld;
import com.fsck.k9.view.MessageTitleView; import com.fsck.k9.view.MessageTitleView;
import com.fsck.k9.view.ViewSwitcher; import com.fsck.k9.view.ViewSwitcher;
import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener; import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener;
@ -88,6 +87,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
private static final int PREVIOUS = 1; private static final int PREVIOUS = 1;
private static final int NEXT = 2; private static final int NEXT = 2;
public static final int REQUEST_CODE_CRYPTO = 1;
public static void actionDisplaySearch(Context context, SearchSpecification search, public static void actionDisplaySearch(Context context, SearchSpecification search,
boolean noThreading, boolean newTask) { boolean noThreading, boolean newTask) {
actionDisplaySearch(context, search, noThreading, newTask, true); actionDisplaySearch(context, search, noThreading, newTask, true);
@ -1562,12 +1563,12 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
// handle OpenPGP results from PendingIntents in OpenPGP view switch (requestCode) {
// must be handled in this main activity, because startIntentSenderForResult() does not support Fragments case REQUEST_CODE_CRYPTO:
MessageOpenPgpViewOld openPgpView = (MessageOpenPgpViewOld) findViewById(R.id.layout_decrypt_openpgp); mMessageViewFragment.handleCryptoResult(resultCode, data);
if (openPgpView != null && openPgpView.handleOnActivityResult(requestCode, resultCode, data)) { break;
return;
} }
} }

View File

@ -329,7 +329,7 @@ public class MessageOpenPgpViewOld extends LinearLayout {
mMissingKeyPI = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); mMissingKeyPI = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
mProgress.setVisibility(View.GONE); mProgress.setVisibility(View.GONE);
mFragment.setMessageWithOpenPgp(output, sigResult); // mFragment.setMessageWithOpenPgp(output, sigResult);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
Log.e(K9.LOG_TAG, "UnsupportedEncodingException", e); Log.e(K9.LOG_TAG, "UnsupportedEncodingException", e);
} }

View File

@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import android.app.Activity; import android.app.Activity;
import android.app.DialogFragment; import android.app.DialogFragment;
@ -20,6 +21,7 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender; import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.Loader; import android.content.Loader;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -41,6 +43,7 @@ import com.fsck.k9.K9;
import com.fsck.k9.Preferences; import com.fsck.k9.Preferences;
import com.fsck.k9.R; import com.fsck.k9.R;
import com.fsck.k9.activity.ChooseFolder; import com.fsck.k9.activity.ChooseFolder;
import com.fsck.k9.activity.MessageList;
import com.fsck.k9.activity.MessageReference; import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.controller.MessagingController; import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.controller.MessagingListener; import com.fsck.k9.controller.MessagingListener;
@ -68,6 +71,7 @@ import com.fsck.k9.ui.message.DecodeMessageLoader;
import com.fsck.k9.ui.message.LocalMessageLoader; import com.fsck.k9.ui.message.LocalMessageLoader;
import com.fsck.k9.view.MessageHeader; import com.fsck.k9.view.MessageHeader;
import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback; import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback;
@ -136,6 +140,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
private Deque<Part> partsToDecrypt; private Deque<Part> partsToDecrypt;
private OpenPgpApi openPgpApi; private OpenPgpApi openPgpApi;
private Part currentlyDecryptingPart; private Part currentlyDecryptingPart;
private Intent currentDecryptingResult;
@Override @Override
@ -329,15 +334,17 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
intent.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, accountName); intent.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, accountName);
try { try {
final CountDownLatch latch = new CountDownLatch(1);
PipedInputStream pipedInputStream = getPipedInputStreamForEncryptedData(); PipedInputStream pipedInputStream = getPipedInputStreamForEncryptedData();
PipedOutputStream decryptedOutputStream = getPipedOutputStreamForDecryptedData(); PipedOutputStream decryptedOutputStream = getPipedOutputStreamForDecryptedData(latch);
openPgpApi.executeApiAsync(intent, pipedInputStream, decryptedOutputStream, new IOpenPgpCallback() { openPgpApi.executeApiAsync(intent, pipedInputStream, decryptedOutputStream, new IOpenPgpCallback() {
@Override @Override
public void onReturn(Intent result) { public void onReturn(Intent result) {
//TODO: check result code Log.d(K9.LOG_TAG, "on result!");
//TODO: signal to AsyncTask in getPipedOutputStreamForDecryptedData() that we have a result code currentDecryptingResult = result;
//TODO: handle RESULT_INTENT latch.countDown();
} }
}); });
} catch (IOException e) { } catch (IOException e) {
@ -366,40 +373,89 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
return pipedInputStream; return pipedInputStream;
} }
private PipedOutputStream getPipedOutputStreamForDecryptedData() throws IOException { private PipedOutputStream getPipedOutputStreamForDecryptedData(final CountDownLatch latch) throws IOException {
PipedOutputStream decryptedOutputStream = new PipedOutputStream(); PipedOutputStream decryptedOutputStream = new PipedOutputStream();
final PipedInputStream decryptedInputStream = new PipedInputStream(decryptedOutputStream); final PipedInputStream decryptedInputStream = new PipedInputStream(decryptedOutputStream);
new AsyncTask<Void, Void, DecryptedBodyPart>() { new AsyncTask<Void, Void, DecryptedBodyPart>() {
@Override @Override
protected DecryptedBodyPart doInBackground(Void... params) { protected DecryptedBodyPart doInBackground(Void... params) {
DecryptedBodyPart decryptedPart = null;
try { try {
DecryptedBodyPart decryptedPart = decryptedPart = DecryptStreamParser.parse(currentlyDecryptingPart, decryptedInputStream);
DecryptStreamParser.parse(currentlyDecryptingPart, decryptedInputStream);
//TODO: wait for IOpenPgpCallback.onReturn() to get the result code and only use latch.await();
// decryptedPart when the decryption was successful } catch (InterruptedException e) {
Log.e(K9.LOG_TAG, "we were interrupted while waiting for onReturn!", e);
return decryptedPart;
} catch (Exception e) { } catch (Exception e) {
Log.e(K9.LOG_TAG, "Something went wrong while parsing the decrypted MIME part", e); Log.e(K9.LOG_TAG, "Something went wrong while parsing the decrypted MIME part", e);
//TODO: pass error to main thread and display error message to user //TODO: pass error to main thread and display error message to user
} }
return decryptedPart;
return null;
} }
@Override @Override
protected void onPostExecute(DecryptedBodyPart decryptedPart) { protected void onPostExecute(DecryptedBodyPart decryptedPart) {
if (decryptedPart == null) { onDecryptionConverge(decryptedPart);
onDecryptionFailed();
} else {
onDecryptionSuccess(decryptedPart);
}
} }
}.execute(); }.execute();
return decryptedOutputStream; return decryptedOutputStream;
} }
private void onDecryptionConverge (DecryptedBodyPart decryptedPart) {
try {
if (currentDecryptingResult == null) {
Log.e(K9.LOG_TAG, "internal error, we should have a result here!");
return;
}
int resultCode = currentDecryptingResult.getIntExtra(OpenPgpApi.RESULT_CODE, -1);
Log.d(K9.LOG_TAG, "result: " + resultCode);
switch (resultCode) {
case -1:
Log.e(K9.LOG_TAG, "internal error: no result code!");
return;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: {
PendingIntent pendingIntent = currentDecryptingResult.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
if (pendingIntent == null) {
throw new AssertionError("Expecting PendingIntent on USER_INTERACTION_REQUIRED!");
}
try {
getActivity().startIntentSenderForResult(pendingIntent.getIntentSender(),
MessageList.REQUEST_CODE_CRYPTO, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.e(K9.LOG_TAG, "internal error on starting pendingintent!", e);
}
return;
}
case OpenPgpApi.RESULT_CODE_ERROR: {
Log.e(K9.LOG_TAG, "error msg: " + currentDecryptingResult.getStringExtra(OpenPgpApi.RESULT_ERROR));
onDecryptionFailed();
return;
}
case OpenPgpApi.RESULT_CODE_SUCCESS: {
onDecryptionSuccess(decryptedPart);
}
}
} finally {
currentDecryptingResult = null;
}
}
public void handleCryptoResult(int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
decryptNextPartOrStartExtractingTextAndAttachments();
} else {
onDecryptionFailed();
}
}
private void onDecryptionSuccess(DecryptedBodyPart decryptedPart) { private void onDecryptionSuccess(DecryptedBodyPart decryptedPart) {
addDecryptedPartToMessage(decryptedPart); addDecryptedPartToMessage(decryptedPart);
onDecryptionFinished(); onDecryptionFinished();
@ -411,7 +467,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
} }
private void onDecryptionFailed() { private void onDecryptionFailed() {
//TODO: display error to user? // TODO: display error to user?
onDecryptionFinished(); onDecryptionFinished();
} }
@ -716,21 +772,6 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
destFolderName, null); destFolderName, null);
} }
/**
* Used by MessageOpenPgpView
*/
public void setMessageWithOpenPgp(String decryptedData, OpenPgpSignatureResult signatureResult) {
try {
// TODO: get rid of PgpData?
PgpData data = new PgpData();
data.setDecryptedData(decryptedData);
data.setSignatureResult(signatureResult);
mMessageView.setMessage(mAccount, messageViewInfo);
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
}
}
private void showDialog(int dialogId) { private void showDialog(int dialogId) {
DialogFragment fragment; DialogFragment fragment;
switch (dialogId) { switch (dialogId) {