mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-24 16:08:49 -05:00
add cancel prevention mechanism, improve cancellation for key import
This commit is contained in:
parent
d17b478a9e
commit
e9a2f256b9
@ -33,6 +33,8 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel;
|
||||
import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType;
|
||||
import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog;
|
||||
import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult;
|
||||
import org.sufficientlysecure.keychain.service.OperationResults.SaveKeyringResult;
|
||||
@ -57,6 +59,7 @@ public class PgpImportExport {
|
||||
|
||||
private Context mContext;
|
||||
private Progressable mProgressable;
|
||||
private AtomicBoolean mCancelled;
|
||||
|
||||
private KeychainServiceListener mKeychainServiceListener;
|
||||
|
||||
@ -73,6 +76,14 @@ public class PgpImportExport {
|
||||
this.mProviderHelper = providerHelper;
|
||||
}
|
||||
|
||||
public PgpImportExport(Context context, ProviderHelper providerHelper, Progressable progressable, AtomicBoolean cancelled) {
|
||||
super();
|
||||
mContext = context;
|
||||
mProgressable = progressable;
|
||||
mProviderHelper = providerHelper;
|
||||
mCancelled = cancelled;
|
||||
}
|
||||
|
||||
public PgpImportExport(Context context,
|
||||
Progressable progressable, KeychainServiceListener keychainListener) {
|
||||
super();
|
||||
@ -126,20 +137,11 @@ public class PgpImportExport {
|
||||
}
|
||||
|
||||
/** Imports keys from given data. If keyIds is given only those are imported */
|
||||
public ImportKeyResult importKeyRings(List<ParcelableKeyRing> entries,
|
||||
AtomicBoolean cancelled) {
|
||||
return importKeyRings(entries.iterator(), entries.size(), cancelled);
|
||||
}
|
||||
|
||||
public ImportKeyResult importKeyRings(List<ParcelableKeyRing> entries) {
|
||||
return importKeyRings(entries.iterator(), entries.size(), null);
|
||||
return importKeyRings(entries.iterator(), entries.size());
|
||||
}
|
||||
|
||||
public ImportKeyResult importKeyRings(Iterator<ParcelableKeyRing> entries, int num) {
|
||||
return importKeyRings(entries, num, null);
|
||||
}
|
||||
public ImportKeyResult importKeyRings(Iterator<ParcelableKeyRing> entries, int num,
|
||||
AtomicBoolean cancelled) {
|
||||
updateProgress(R.string.progress_importing, 0, 100);
|
||||
|
||||
// If there aren't even any keys, do nothing here.
|
||||
@ -154,8 +156,7 @@ public class PgpImportExport {
|
||||
double progSteps = 100.0 / num;
|
||||
for (ParcelableKeyRing entry : new IterableIterator<ParcelableKeyRing>(entries)) {
|
||||
// Has this action been cancelled? If so, don't proceed any further
|
||||
if (cancelled != null && cancelled.get()) {
|
||||
Log.d(Constants.TAG, "CANCELLED!");
|
||||
if (mCancelled != null && mCancelled.get()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -227,7 +228,8 @@ public class PgpImportExport {
|
||||
resultType |= ImportKeyResult.RESULT_WARNINGS;
|
||||
}
|
||||
}
|
||||
if (cancelled != null && cancelled.get()) {
|
||||
if (mCancelled != null && mCancelled.get()) {
|
||||
log.add(LogLevel.CANCELLED, LogType.MSG_OPERATION_CANCELLED, 0);
|
||||
resultType |= ImportKeyResult.RESULT_CANCELLED;
|
||||
}
|
||||
|
||||
|
@ -526,12 +526,17 @@ public class KeychainIntentService extends IntentService
|
||||
}
|
||||
|
||||
ProviderHelper providerHelper = new ProviderHelper(this);
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(this, providerHelper, this);
|
||||
ImportKeyResult result = pgpImportExport.importKeyRings(entries, mActionCanceled);
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(
|
||||
this, providerHelper, this, mActionCanceled);
|
||||
ImportKeyResult result = pgpImportExport.importKeyRings(entries);
|
||||
|
||||
// we do this even on failure or cancellation!
|
||||
if (result.mSecret > 0) {
|
||||
// cannot cancel from here on out!
|
||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_PREVENT_CANCEL);
|
||||
providerHelper.consolidateDatabaseStep1(this);
|
||||
}
|
||||
|
||||
// make sure new data is synced into contacts
|
||||
ContactSyncAdapterService.requestSync();
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@ -37,6 +36,7 @@ public class KeychainIntentServiceHandler extends Handler {
|
||||
public static final int MESSAGE_OKAY = 1;
|
||||
public static final int MESSAGE_EXCEPTION = 2;
|
||||
public static final int MESSAGE_UPDATE_PROGRESS = 3;
|
||||
public static final int MESSAGE_PREVENT_CANCEL = 4;
|
||||
|
||||
// possible data keys for messages
|
||||
public static final String DATA_ERROR = "error";
|
||||
@ -124,6 +124,9 @@ public class KeychainIntentServiceHandler extends Handler {
|
||||
|
||||
break;
|
||||
|
||||
case MESSAGE_PREVENT_CANCEL:
|
||||
mProgressDialogFragment.setPreventCancel(true);
|
||||
|
||||
default:
|
||||
Log.e(Constants.TAG, "unknown handler message!");
|
||||
break;
|
||||
|
@ -44,7 +44,6 @@ import org.sufficientlysecure.keychain.service.OperationResults;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Notify;
|
||||
|
||||
public class CreateKeyFinalFragment extends Fragment {
|
||||
|
||||
|
@ -23,6 +23,7 @@ import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnKeyListener;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.ContextThemeWrapper;
|
||||
@ -39,6 +40,8 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
private static final String ARG_STYLE = "style";
|
||||
private static final String ARG_CANCELABLE = "cancelable";
|
||||
|
||||
boolean mCanCancel = false, mPreventCancel = false, mIsCancelled = false;
|
||||
|
||||
/** Creates new instance of this fragment */
|
||||
public static ProgressDialogFragment newInstance(String message, int style, boolean cancelable) {
|
||||
ProgressDialogFragment frag = new ProgressDialogFragment();
|
||||
@ -59,6 +62,10 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
|
||||
/** Updates progress of dialog */
|
||||
public void setProgress(int progress, int max) {
|
||||
if (mIsCancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
|
||||
dialog.setProgress(progress);
|
||||
@ -67,6 +74,10 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
|
||||
/** Updates progress of dialog */
|
||||
public void setProgress(String message, int progress, int max) {
|
||||
if (mIsCancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
|
||||
dialog.setMessage(message);
|
||||
@ -94,13 +105,13 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
|
||||
String message = getArguments().getString(ARG_MESSAGE);
|
||||
int style = getArguments().getInt(ARG_STYLE);
|
||||
final boolean cancelable = getArguments().getBoolean(ARG_CANCELABLE);
|
||||
mCanCancel = getArguments().getBoolean(ARG_CANCELABLE);
|
||||
|
||||
dialog.setMessage(message);
|
||||
dialog.setProgressStyle(style);
|
||||
|
||||
// If this is supposed to be cancelable, add our (custom) cancel mechanic
|
||||
if (cancelable) {
|
||||
if (mCanCancel) {
|
||||
// Just show the button, take care of the onClickListener afterwards (in onStart)
|
||||
dialog.setButton(DialogInterface.BUTTON_NEGATIVE,
|
||||
activity.getString(R.string.progress_cancel), (DialogInterface.OnClickListener) null);
|
||||
@ -111,7 +122,7 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (cancelable) {
|
||||
if (mCanCancel) {
|
||||
((ProgressDialog) dialog).getButton(
|
||||
DialogInterface.BUTTON_NEGATIVE).performClick();
|
||||
}
|
||||
@ -126,15 +137,41 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public void setPreventCancel(boolean preventCancel) {
|
||||
// Don't care if we can't cancel anymore either way!
|
||||
if (mIsCancelled || ! mCanCancel) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPreventCancel = preventCancel;
|
||||
final Button negative = ((ProgressDialog) getDialog()).getButton(DialogInterface.BUTTON_NEGATIVE);
|
||||
negative.setVisibility(preventCancel ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// Override the default behavior so the dialog is NOT dismissed on click
|
||||
Button negative = ((ProgressDialog) getDialog()).getButton(DialogInterface.BUTTON_NEGATIVE);
|
||||
final Button negative = ((ProgressDialog) getDialog()).getButton(DialogInterface.BUTTON_NEGATIVE);
|
||||
negative.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// nvm if we are already cancelled, or weren't able to begin with
|
||||
if (mIsCancelled || ! mCanCancel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember this, and don't allow another click
|
||||
mIsCancelled = true;
|
||||
negative.setClickable(false);
|
||||
negative.setTextColor(Color.GRAY);
|
||||
|
||||
// Set the progress bar accordingly
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setMessage(getString(R.string.progress_cancelling));
|
||||
|
||||
// send a cancel message. note that this message will be handled by
|
||||
// KeychainIntentService.onStartCommand, which runs in this thread,
|
||||
// not the service one, and will not queue up a command.
|
||||
|
Loading…
Reference in New Issue
Block a user