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