mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 11:12:15 -05:00
parent
38c6cf045c
commit
7da7832284
@ -121,14 +121,7 @@ public class ExportHelper {
|
||||
// Message is received after exporting is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(mActivity,
|
||||
mActivity.getString(R.string.progress_exporting),
|
||||
ProgressDialog.STYLE_HORIZONTAL,
|
||||
true,
|
||||
new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialogInterface) {
|
||||
mActivity.stopService(intent);
|
||||
}
|
||||
}) {
|
||||
ProgressDialog.STYLE_HORIZONTAL) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard KeychainIntentServiceHandler first
|
||||
super.handleMessage(message);
|
||||
|
@ -46,6 +46,7 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class PgpImportExport {
|
||||
|
||||
@ -125,11 +126,20 @@ 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());
|
||||
return importKeyRings(entries.iterator(), entries.size(), null);
|
||||
}
|
||||
|
||||
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.
|
||||
@ -143,6 +153,12 @@ public class PgpImportExport {
|
||||
int position = 0;
|
||||
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!");
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
UncachedKeyRing key = UncachedKeyRing.decodeFromData(entry.getBytes());
|
||||
|
||||
@ -208,9 +224,12 @@ public class PgpImportExport {
|
||||
}
|
||||
}
|
||||
if (log.containsWarnings()) {
|
||||
resultType |= ImportKeyResult.RESULT_WITH_WARNINGS;
|
||||
resultType |= ImportKeyResult.RESULT_WARNINGS;
|
||||
}
|
||||
}
|
||||
if (cancelled != null && cancelled.get()) {
|
||||
resultType |= ImportKeyResult.RESULT_CANCELLED;
|
||||
}
|
||||
|
||||
return new ImportKeyResult(resultType, log, newKeys, oldKeys, badKeys, secret);
|
||||
|
||||
|
@ -72,6 +72,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This Service contains all important long lasting operations for APG. It receives Intents with
|
||||
@ -110,6 +111,8 @@ public class KeychainIntentService extends IntentService
|
||||
|
||||
public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE";
|
||||
|
||||
public static final String ACTION_CANCEL = Constants.INTENT_PREFIX + "CANCEL";
|
||||
|
||||
/* keys for data bundle */
|
||||
|
||||
// encrypt, decrypt, import export
|
||||
@ -196,6 +199,8 @@ public class KeychainIntentService extends IntentService
|
||||
Messenger mMessenger;
|
||||
|
||||
private boolean mIsCanceled;
|
||||
// this attribute can possibly merged with the one above? not sure...
|
||||
private AtomicBoolean mActionCanceled = new AtomicBoolean(false);
|
||||
|
||||
public KeychainIntentService() {
|
||||
super("KeychainIntentService");
|
||||
@ -214,6 +219,10 @@ public class KeychainIntentService extends IntentService
|
||||
*/
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
|
||||
// We have not been cancelled! (yet)
|
||||
mActionCanceled.set(false);
|
||||
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras == null) {
|
||||
Log.e(Constants.TAG, "Extras bundle is null!");
|
||||
@ -500,7 +509,7 @@ public class KeychainIntentService extends IntentService
|
||||
|
||||
ProviderHelper providerHelper = new ProviderHelper(this);
|
||||
PgpImportExport pgpImportExport = new PgpImportExport(this, providerHelper, this);
|
||||
ImportKeyResult result = pgpImportExport.importKeyRings(entries);
|
||||
ImportKeyResult result = pgpImportExport.importKeyRings(entries, mActionCanceled);
|
||||
|
||||
if (result.mSecret > 0) {
|
||||
providerHelper.consolidateDatabaseStep1(this);
|
||||
@ -612,7 +621,6 @@ public class KeychainIntentService extends IntentService
|
||||
|
||||
ArrayList<ParcelableKeyRing> keyRings = new ArrayList<ParcelableKeyRing>(entries.size());
|
||||
for (ImportKeysListEntry entry : entries) {
|
||||
|
||||
Keyserver server;
|
||||
if (entry.getOrigin() == null) {
|
||||
server = new HkpKeyserver(keyServer);
|
||||
@ -874,6 +882,15 @@ public class KeychainIntentService extends IntentService
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (ACTION_CANCEL.equals(intent.getAction())) {
|
||||
mActionCanceled.set(true);
|
||||
return START_STICKY;
|
||||
}
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
private String getOriginalFilename(Bundle data) throws PgpGeneralException, FileNotFoundException {
|
||||
int target = data.getInt(TARGET);
|
||||
switch (target) {
|
||||
|
@ -60,18 +60,16 @@ public class KeychainIntentServiceHandler extends Handler {
|
||||
|
||||
public KeychainIntentServiceHandler(Activity activity, String progressDialogMessage,
|
||||
int progressDialogStyle) {
|
||||
this(activity, progressDialogMessage, progressDialogStyle, false, null);
|
||||
this(activity, progressDialogMessage, progressDialogStyle, false);
|
||||
}
|
||||
|
||||
public KeychainIntentServiceHandler(Activity activity, String progressDialogMessage,
|
||||
int progressDialogStyle, boolean cancelable,
|
||||
OnCancelListener onCancelListener) {
|
||||
int progressDialogStyle, boolean cancelable) {
|
||||
this.mActivity = activity;
|
||||
this.mProgressDialogFragment = ProgressDialogFragment.newInstance(
|
||||
progressDialogMessage,
|
||||
progressDialogStyle,
|
||||
cancelable,
|
||||
onCancelListener);
|
||||
cancelable);
|
||||
}
|
||||
|
||||
public void showProgressDialog(FragmentActivity activity) {
|
||||
|
@ -55,13 +55,17 @@ public class OperationResultParcel implements Parcelable {
|
||||
|
||||
public static final String EXTRA_RESULT = "operation_result";
|
||||
|
||||
/** Holds the overall result, the number specifying varying degrees of success. The first bit
|
||||
* is 0 on overall success, 1 on overall failure. All other bits may be used for more specific
|
||||
* conditions. */
|
||||
/** Holds the overall result, the number specifying varying degrees of success:
|
||||
* - The first bit is 0 on overall success, 1 on overall failure
|
||||
* - The second bit indicates if the action was cancelled - may still be an error or success!
|
||||
* - The third bit should be set if the operation succeeded with warnings
|
||||
* All other bits may be used for more specific conditions. */
|
||||
final int mResult;
|
||||
|
||||
public static final int RESULT_OK = 0;
|
||||
public static final int RESULT_ERROR = 1;
|
||||
public static final int RESULT_CANCELLED = 2;
|
||||
public static final int RESULT_WARNINGS = 4;
|
||||
|
||||
/// A list of log entries tied to the operation result.
|
||||
final OperationLog mLog;
|
||||
|
@ -26,6 +26,7 @@ import android.view.View;
|
||||
|
||||
import com.github.johnpersano.supertoasts.SuperCardToast;
|
||||
import com.github.johnpersano.supertoasts.SuperToast;
|
||||
import com.github.johnpersano.supertoasts.SuperToast.Duration;
|
||||
import com.github.johnpersano.supertoasts.util.OnClickWrapper;
|
||||
import com.github.johnpersano.supertoasts.util.Style;
|
||||
|
||||
@ -44,16 +45,14 @@ public abstract class OperationResults {
|
||||
public final int mNewKeys, mUpdatedKeys, mBadKeys, mSecret;
|
||||
|
||||
// At least one new key
|
||||
public static final int RESULT_OK_NEWKEYS = 2;
|
||||
public static final int RESULT_OK_NEWKEYS = 8;
|
||||
// At least one updated key
|
||||
public static final int RESULT_OK_UPDATED = 4;
|
||||
public static final int RESULT_OK_UPDATED = 16;
|
||||
// At least one key failed (might still be an overall success)
|
||||
public static final int RESULT_WITH_ERRORS = 8;
|
||||
// There are warnings in the log
|
||||
public static final int RESULT_WITH_WARNINGS = 16;
|
||||
public static final int RESULT_WITH_ERRORS = 32;
|
||||
|
||||
// No keys to import...
|
||||
public static final int RESULT_FAIL_NOTHING = 32 + 1;
|
||||
public static final int RESULT_FAIL_NOTHING = 64 + 1;
|
||||
|
||||
public boolean isOkBoth() {
|
||||
return (mResult & (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED))
|
||||
@ -119,15 +118,20 @@ public abstract class OperationResults {
|
||||
if ((resultType & OperationResultParcel.RESULT_ERROR) == 0) {
|
||||
String withWarnings;
|
||||
|
||||
duration = Duration.EXTRA_LONG;
|
||||
color = Style.GREEN;
|
||||
withWarnings = "";
|
||||
|
||||
// Any warnings?
|
||||
if ((resultType & ImportKeyResult.RESULT_WITH_WARNINGS) > 0) {
|
||||
if ((resultType & ImportKeyResult.RESULT_WARNINGS) > 0) {
|
||||
duration = 0;
|
||||
color = Style.ORANGE;
|
||||
withWarnings = activity.getResources().getString(R.string.import_with_warnings);
|
||||
} else {
|
||||
duration = SuperToast.Duration.LONG;
|
||||
color = Style.GREEN;
|
||||
withWarnings = "";
|
||||
withWarnings += activity.getString(R.string.import_with_warnings);
|
||||
}
|
||||
if ((resultType & ImportKeyResult.RESULT_CANCELLED) > 0) {
|
||||
duration = 0;
|
||||
color = Style.ORANGE;
|
||||
withWarnings += activity.getString(R.string.import_with_cancelled);
|
||||
}
|
||||
|
||||
// New and updated keys
|
||||
@ -152,13 +156,14 @@ public abstract class OperationResults {
|
||||
duration = 0;
|
||||
color = Style.RED;
|
||||
if (isFailNothing()) {
|
||||
str = activity.getString(R.string.import_error_nothing);
|
||||
str = activity.getString((resultType & ImportKeyResult.RESULT_CANCELLED) > 0
|
||||
? R.string.import_error_nothing_cancelled
|
||||
: R.string.import_error_nothing);
|
||||
} else {
|
||||
str = activity.getString(R.string.import_error);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: externalize into Notify class?
|
||||
boolean button = getLog() != null && !getLog().isEmpty();
|
||||
SuperCardToast toast = new SuperCardToast(activity,
|
||||
button ? SuperToast.Type.BUTTON : SuperToast.Type.STANDARD,
|
||||
@ -243,7 +248,7 @@ public abstract class OperationResults {
|
||||
}
|
||||
|
||||
// Some old key was updated
|
||||
public static final int UPDATED = 2;
|
||||
public static final int UPDATED = 4;
|
||||
|
||||
// Public key was saved
|
||||
public static final int SAVED_PUBLIC = 8;
|
||||
|
@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NdefMessage;
|
||||
@ -447,7 +449,8 @@ public class ImportKeysActivity extends ActionBarActivity {
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||
this,
|
||||
getString(R.string.progress_importing),
|
||||
ProgressDialog.STYLE_HORIZONTAL) {
|
||||
ProgressDialog.STYLE_HORIZONTAL,
|
||||
true) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard KeychainIntentServiceHandler first
|
||||
super.handleMessage(message);
|
||||
|
@ -21,32 +21,26 @@ import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnKeyListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
|
||||
public class ProgressDialogFragment extends DialogFragment {
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
private static final String ARG_STYLE = "style";
|
||||
private static final String ARG_CANCELABLE = "cancelable";
|
||||
|
||||
private OnCancelListener mOnCancelListener;
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*
|
||||
* @param message
|
||||
* @param style
|
||||
* @param cancelable
|
||||
* @return
|
||||
*/
|
||||
public static ProgressDialogFragment newInstance(String message, int style, boolean cancelable,
|
||||
OnCancelListener onCancelListener) {
|
||||
/** Creates new instance of this fragment */
|
||||
public static ProgressDialogFragment newInstance(String message, int style, boolean cancelable) {
|
||||
ProgressDialogFragment frag = new ProgressDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
@ -54,28 +48,16 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
args.putBoolean(ARG_CANCELABLE, cancelable);
|
||||
|
||||
frag.setArguments(args);
|
||||
frag.mOnCancelListener = onCancelListener;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates progress of dialog
|
||||
*
|
||||
* @param messageId
|
||||
* @param progress
|
||||
* @param max
|
||||
*/
|
||||
/** Updates progress of dialog */
|
||||
public void setProgress(int messageId, int progress, int max) {
|
||||
setProgress(getString(messageId), progress, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates progress of dialog
|
||||
*
|
||||
* @param progress
|
||||
* @param max
|
||||
*/
|
||||
/** Updates progress of dialog */
|
||||
public void setProgress(int progress, int max) {
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
|
||||
@ -83,13 +65,7 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
dialog.setMax(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates progress of dialog
|
||||
*
|
||||
* @param message
|
||||
* @param progress
|
||||
* @param max
|
||||
*/
|
||||
/** Updates progress of dialog */
|
||||
public void setProgress(String message, int progress, int max) {
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
|
||||
@ -98,15 +74,6 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
dialog.setMax(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
|
||||
if (this.mOnCancelListener != null) {
|
||||
this.mOnCancelListener.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dialog
|
||||
*/
|
||||
@ -121,41 +88,62 @@ public class ProgressDialogFragment extends DialogFragment {
|
||||
|
||||
ProgressDialog dialog = new ProgressDialog(context);
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
// We never use the builtin cancel method
|
||||
dialog.setCancelable(false);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
|
||||
String message = getArguments().getString(ARG_MESSAGE);
|
||||
int style = getArguments().getInt(ARG_STYLE);
|
||||
boolean cancelable = getArguments().getBoolean(ARG_CANCELABLE);
|
||||
final boolean cancelable = getArguments().getBoolean(ARG_CANCELABLE);
|
||||
|
||||
dialog.setMessage(message);
|
||||
dialog.setProgressStyle(style);
|
||||
|
||||
// If this is supposed to be cancelable, add our (custom) cancel mechanic
|
||||
if (cancelable) {
|
||||
// Just show the button, take care of the onClickListener afterwards (in onStart)
|
||||
dialog.setButton(DialogInterface.BUTTON_NEGATIVE,
|
||||
activity.getString(R.string.progress_cancel),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
activity.getString(R.string.progress_cancel), (DialogInterface.OnClickListener) null);
|
||||
}
|
||||
|
||||
// Disable the back button
|
||||
// Disable the back button regardless
|
||||
OnKeyListener keyListener = new OnKeyListener() {
|
||||
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (cancelable) {
|
||||
((ProgressDialog) dialog).getButton(
|
||||
DialogInterface.BUTTON_NEGATIVE).performClick();
|
||||
}
|
||||
// return true, indicating we handled this
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
dialog.setOnKeyListener(keyListener);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@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);
|
||||
negative.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// 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.
|
||||
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
|
||||
intent.setAction(KeychainIntentService.ACTION_CANCEL);
|
||||
getActivity().startService(intent);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -381,8 +381,10 @@
|
||||
</plurals>
|
||||
<string name="view_log">View Log</string>
|
||||
<string name="import_error_nothing">Nothing to import.</string>
|
||||
<string name="import_error_nothing_cancelled">Import cancelled.</string>
|
||||
<string name="import_error">Error importing keys!</string>
|
||||
<string name="import_with_warnings">, with warnings</string>
|
||||
<string name="import_with_cancelled">, until cancelled</string>
|
||||
|
||||
<!-- Intent labels -->
|
||||
<string name="intent_decrypt_file">Decrypt File with OpenKeychain</string>
|
||||
|
Loading…
Reference in New Issue
Block a user