0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-20 12:12:15 +02:00

messageview: cancel operation when fragment is destroyed

This commit is contained in:
Vincent Breitmoser 2016-05-10 16:00:41 +02:00 committed by Vincent Breitmoser
parent 9b1e51c559
commit 68e31a985f
4 changed files with 89 additions and 21 deletions

View File

@ -42,6 +42,7 @@ import org.openintents.openpgp.OpenPgpDecryptionResult;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpApi.CancelableBackgroundOperation;
import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpSinkResultCallback;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSink;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
@ -69,6 +70,8 @@ public class MessageCryptoHelper {
private Intent userInteractionResultIntent;
private LocalMessage currentMessage;
private boolean secondPassStarted;
private CancelableBackgroundOperation cancelableBackgroundOperation;
private boolean isCancelled;
public MessageCryptoHelper(Activity activity, Account account, MessageCryptoCallback callback) {
@ -151,6 +154,10 @@ public class MessageCryptoHelper {
}
private void decryptOrVerifyNextPart() {
if (isCancelled) {
return;
}
if (partsToDecryptOrVerify.isEmpty()) {
runSecondPassOrReturnResultToFragment();
return;
@ -232,7 +239,8 @@ public class MessageCryptoHelper {
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
OpenPgpDataSink<MimeBodyPart> dataSink = getDataSinkForDecryptedInlineData();
openPgpApi.executeApiAsync(intent, dataSource, dataSink, new IOpenPgpSinkResultCallback<MimeBodyPart>() {
cancelableBackgroundOperation = openPgpApi.executeApiAsync(intent, dataSource, dataSink,
new IOpenPgpSinkResultCallback<MimeBodyPart>() {
@Override
public void onProgress(int current, int max) {
Log.d(K9.LOG_TAG, "received progress status: " + current + " / " + max);
@ -247,6 +255,13 @@ public class MessageCryptoHelper {
});
}
public void cancelIfRunning() {
isCancelled = true;
if (cancelableBackgroundOperation != null) {
cancelableBackgroundOperation.cancelOperation();
}
}
private OpenPgpDataSink<MimeBodyPart> getDataSinkForDecryptedInlineData() {
return new OpenPgpDataSink<MimeBodyPart>() {
@Override
@ -269,7 +284,8 @@ public class MessageCryptoHelper {
OpenPgpDataSource dataSource = getDataSourceForEncryptedOrInlineData();
OpenPgpDataSink<MimeBodyPart> openPgpDataSink = getDataSinkForDecryptedData();
openPgpApi.executeApiAsync(intent, dataSource, openPgpDataSink, new IOpenPgpSinkResultCallback<MimeBodyPart>() {
cancelableBackgroundOperation = openPgpApi.executeApiAsync(intent, dataSource, openPgpDataSink,
new IOpenPgpSinkResultCallback<MimeBodyPart>() {
@Override
public void onReturn(Intent result, MimeBodyPart decryptedPart) {
currentCryptoResult = result;
@ -462,6 +478,10 @@ public class MessageCryptoHelper {
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (isCancelled) {
return;
}
if (requestCode != REQUEST_CODE_USER_INTERACTION) {
throw new IllegalStateException("got an activity result that wasn't meant for us. this is a bug!");
}
@ -526,7 +546,6 @@ public class MessageCryptoHelper {
callback.onCryptoOperationsFinished(messageAnnotations);
}
private static class CryptoPart {
public final CryptoPartType type;
public final Part part;

View File

@ -19,6 +19,7 @@ import android.content.Loader;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.UiThread;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextThemeWrapper;
@ -144,6 +145,14 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
mInitialized = true;
}
@UiThread
private void cancelAndClearMessageCryptoHelper() {
if (messageCryptoHelper != null) {
messageCryptoHelper.cancelIfRunning();
messageCryptoHelper = null;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@ -233,6 +242,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
getLoaderManager().initLoader(LOCAL_MESSAGE_LOADER_ID, null, localMessageLoaderCallback);
}
@UiThread
private void onLoadMessageFromDatabaseFinished(LocalMessage message) {
displayMessageHeader(message);

View File

@ -35,6 +35,7 @@ import android.util.Log;
import org.openintents.openpgp.IOpenPgpService2;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.ParcelFileDescriptorUtil.DataSinkTransferThread;
import org.openintents.openpgp.util.ParcelFileDescriptorUtil.DataSourceTransferThread;
@SuppressWarnings("unused")
@ -288,7 +289,12 @@ public class OpenPgpApi {
void onReturn(final Intent result, T sinkResult);
}
private class OpenPgpSourceSinkAsyncTask<T> extends AsyncTask<Void, Integer, OpenPgpDataResult<T>> {
public interface CancelableBackgroundOperation {
void cancelOperation();
}
private class OpenPgpSourceSinkAsyncTask<T> extends AsyncTask<Void, Integer, OpenPgpDataResult<T>>
implements CancelableBackgroundOperation {
Intent data;
OpenPgpDataSource dataSource;
OpenPgpDataSink<T> dataSink;
@ -310,6 +316,14 @@ public class OpenPgpApi {
protected void onPostExecute(OpenPgpDataResult<T> result) {
callback.onReturn(result.apiResult, result.sinkResult);
}
@Override
public void cancelOperation() {
cancel(true);
if (dataSource != null) {
dataSource.cancel();
}
}
}
private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Intent> {
@ -335,8 +349,8 @@ public class OpenPgpApi {
}
}
public <T> void executeApiAsync(Intent data, OpenPgpDataSource dataSource, OpenPgpDataSink<T> dataSink,
final IOpenPgpSinkResultCallback<T> callback) {
public <T> CancelableBackgroundOperation executeApiAsync(Intent data, OpenPgpDataSource dataSource,
OpenPgpDataSink<T> dataSink, final IOpenPgpSinkResultCallback<T> callback) {
Messenger messenger = new Messenger(new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
@ -356,9 +370,10 @@ public class OpenPgpApi {
task.execute((Void[]) null);
}
return task;
}
public void executeApiAsync(Intent data, OpenPgpDataSource dataSource, IOpenPgpSinkResultCallback<Void> callback) {
public AsyncTask executeApiAsync(Intent data, OpenPgpDataSource dataSource, IOpenPgpSinkResultCallback<Void> callback) {
OpenPgpSourceSinkAsyncTask<Void> task = new OpenPgpSourceSinkAsyncTask<>(data, dataSource, null, callback);
// don't serialize async tasks!
@ -369,6 +384,7 @@ public class OpenPgpApi {
task.execute((Void[]) null);
}
return task;
}
public void executeApiAsync(Intent data, InputStream is, OutputStream os, IOpenPgpCallback callback) {
@ -404,7 +420,7 @@ public class OpenPgpApi {
} else {
data.removeExtra(EXTRA_PROGRESS_MESSENGER);
}
input = ParcelFileDescriptorUtil.asyncPipeFromDataSource(dataSource);
input = dataSource.startPumpThread();
}
DataSinkTransferThread<T> pumpThread = null;
@ -487,10 +503,41 @@ public class OpenPgpApi {
}
public static abstract class OpenPgpDataSource {
private boolean isCancelled;
private ParcelFileDescriptor writeSidePfd;
public abstract void writeTo(OutputStream os) throws IOException;
public Long getSizeForProgress() {
return null;
}
public boolean isCancelled() {
return isCancelled;
}
private ParcelFileDescriptor startPumpThread() throws IOException {
if (writeSidePfd != null) {
throw new IllegalStateException("startPumpThread() must only be called once!");
}
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor readSidePfd = pipe[0];
writeSidePfd = pipe[1];
new DataSourceTransferThread(this, new ParcelFileDescriptor.AutoCloseOutputStream(writeSidePfd)).start();
return readSidePfd;
}
private void cancel() {
isCancelled = true;
try {
writeSidePfd.close();
} catch (IOException e) {
// this is fine
}
}
}
public interface OpenPgpDataSink<T> {
@ -508,7 +555,7 @@ public class OpenPgpApi {
} else {
data.removeExtra(EXTRA_PROGRESS_MESSENGER);
}
input = ParcelFileDescriptorUtil.asyncPipeFromDataSource(dataSource);
input = dataSource.startPumpThread();
}
Thread pumpThread = null;

View File

@ -99,16 +99,6 @@ public class ParcelFileDescriptorUtil {
return dataSinkTransferThread;
}
public static ParcelFileDescriptor asyncPipeFromDataSource(OpenPgpDataSource dataSource) throws IOException {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor readSide = pipe[0];
ParcelFileDescriptor writeSide = pipe[1];
new DataSourceTransferThread(dataSource, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide)).start();
return readSide;
}
static class DataSourceTransferThread extends Thread {
final OpenPgpDataSource dataSource;
final OutputStream outputStream;
@ -125,8 +115,10 @@ public class ParcelFileDescriptorUtil {
try {
dataSource.writeTo(outputStream);
} catch (IOException e) {
if (isIOExceptionCausedByEPIPE(e)) {
Log.e(OpenPgpApi.TAG, "Stopped writing due to broken pipe (other end closed pipe?)");
if (dataSource.isCancelled()) {
Log.d(OpenPgpApi.TAG, "Stopped writing because operation was cancelled.");
} else if (isIOExceptionCausedByEPIPE(e)) {
Log.d(OpenPgpApi.TAG, "Stopped writing due to broken pipe (other end closed pipe?)");
} else {
Log.e(OpenPgpApi.TAG, "IOException when writing to out", e);
}