From fcd27d2600711ccd32c000c6d58da19cb816a9bf Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Thu, 9 Jul 2015 22:51:20 +0530 Subject: implemented revocation on deletion --- .../keychain/ui/DeleteKeyDialogActivity.java | 231 ++++++++++++++++++ .../keychain/ui/EditKeyFragment.java | 1 + .../keychain/ui/KeyListFragment.java | 70 +++--- .../keychain/ui/RevokeDeleteDialogActivity.java | 258 +++++++++++++++++++++ .../keychain/ui/ViewKeyActivity.java | 50 ++-- .../keychain/ui/base/CryptoOperationHelper.java | 34 +-- .../ui/dialog/DeleteKeyDialogFragment.java | 211 ----------------- 7 files changed, 570 insertions(+), 285 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java new file mode 100644 index 000000000..064d34e38 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -0,0 +1,231 @@ +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.HashMap; + +public class DeleteKeyDialogActivity extends FragmentActivity + implements CryptoOperationHelper.Callback { + public static final String EXTRA_DELETE_MASTER_KEY_IDS = "extra_delete_master_key_ids"; + + private CryptoOperationHelper mDeleteOpHelper; + + private long[] mMasterKeyIds; + private boolean mHasSecret; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mDeleteOpHelper = new CryptoOperationHelper<>(DeleteKeyDialogActivity.this, + DeleteKeyDialogActivity.this, R.string.progress_deleting); + mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); + + mMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_DELETE_MASTER_KEY_IDS); + + Handler deleteDialogHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == DeleteKeyDialogFragment.MESSAGE_PERFORM_DELETE) { + mHasSecret = msg.getData().getBoolean(DeleteKeyDialogFragment.MSG_HAS_SECRET); + mDeleteOpHelper.cryptoOperation(); + } + } + }; + + Messenger messenger = new Messenger(deleteDialogHandler); + + DeleteKeyDialogFragment deleteKeyDialogFragment + = DeleteKeyDialogFragment.newInstance(messenger, mMasterKeyIds); + + deleteKeyDialogFragment.show(getSupportFragmentManager(), "deleteKeyDialog"); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mDeleteOpHelper.onSaveInstanceState(outState); + } + + @Override + public DeleteKeyringParcel createOperationInput() { + return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); + } + + @Override + public void onCryptoOperationSuccess(DeleteResult result) { + handleResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(DeleteResult result) { + handleResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + + public void handleResult(DeleteResult result) { + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, result); + setResult(RESULT_OK, intent); + finish(); + } + + public static class DeleteKeyDialogFragment extends DialogFragment { + + public static final String MSG_HAS_SECRET = "msg_has_secret"; + + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; + + public static final int MESSAGE_PERFORM_DELETE = 1; + + private TextView mMainMessage; + private View mInflateView; + + private Messenger mMessenger; + /** + * Creates new instance of this delete file dialog fragment + */ + public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] masterKeyIds) { + DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); + Bundle args = new Bundle(); + + args.putParcelable(ARG_MESSENGER, messenger); + args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); + + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity activity = getActivity(); + mMessenger = getArguments().getParcelable(ARG_MESSENGER); + + final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); + + ContextThemeWrapper theme = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme); + + // Setup custom View to display in AlertDialog + LayoutInflater inflater = activity.getLayoutInflater(); + mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); + builder.setView(mInflateView); + + mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage); + + final boolean hasSecret; + + // If only a single key has been selected + if (masterKeyIds.length == 1) { + long masterKeyId = masterKeyIds[0]; + + try { + HashMap data = new ProviderHelper(activity).getUnifiedData( + masterKeyId, new String[]{ + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.HAS_ANY_SECRET + }, new int[]{ + ProviderHelper.FIELD_TYPE_STRING, + ProviderHelper.FIELD_TYPE_INTEGER + } + ); + String name; + KeyRing.UserId mainUserId = KeyRing.splitUserId((String) data.get(KeychainContract.KeyRings.USER_ID)); + if (mainUserId.name != null) { + name = mainUserId.name; + } else { + name = getString(R.string.user_id_no_name); + } + hasSecret = ((Long) data.get(KeychainContract.KeyRings.HAS_ANY_SECRET)) == 1; + + if (hasSecret) { + // show title only for secret key deletions, + // see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior + builder.setTitle(getString(R.string.title_delete_secret_key, name)); + mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name)); + } else { + mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name)); + } + } catch (ProviderHelper.NotFoundException e) { + dismiss(); + return null; + } + } else { + mMainMessage.setText(R.string.key_deletion_confirmation_multi); + hasSecret = false; + } + + builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + Bundle data = new Bundle(); + data.putBoolean(MSG_HAS_SECRET, hasSecret); + Message msg = Message.obtain(); + msg.setData(data); + msg.what = MESSAGE_PERFORM_DELETE; + try { + mMessenger.send(msg); + } catch (RemoteException e) { + Log.e(Constants.TAG, "messenger error", e); + } + } + }); + + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + getActivity().finish(); + } + }); + + return builder.show(); + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 4e9c5a836..f750c6d97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -410,6 +410,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment { static final int REQUEST_ACTION = 1; + private static final int REQUEST_DELETE = 2; + private static final int REQUEST_VIEW_KEY = 3; private KeyListAdapter mAdapter; private StickyListHeadersListView mStickyList; @@ -336,7 +338,7 @@ public class KeyListFragment extends LoaderFragment Intent viewIntent = new Intent(getActivity(), ViewKeyActivity.class); viewIntent.setData( KeyRings.buildGenericKeyRingUri(mAdapter.getMasterKeyId(position))); - startActivity(viewIntent); + startActivityForResult(viewIntent, REQUEST_VIEW_KEY); } protected void encrypt(ActionMode mode, long[] masterKeyIds) { @@ -362,30 +364,9 @@ public class KeyListFragment extends LoaderFragment return; } - // Message is received after key is deleted - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.arg1 == DeleteKeyDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - if (data != null) { - DeleteResult result = data.getParcelable(DeleteResult.EXTRA_RESULT); - if (result != null) { - result.createNotify(getActivity()).show(); - } - } - mode.finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - masterKeyIds); - - deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); + Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class); + intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, masterKeyIds); + startActivityForResult(intent, REQUEST_DELETE); } @@ -620,14 +601,35 @@ public class KeyListFragment extends LoaderFragment mConsolidateOpHelper.handleActivityResult(requestCode, resultCode, data); } - if (requestCode == REQUEST_ACTION) { - // if a result has been returned, display a notify - if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { - OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); - result.createNotify(getActivity()).show(); - } else { - super.onActivityResult(requestCode, resultCode, data); - } + switch (requestCode) { + case REQUEST_DELETE: + mActionMode.finish(); + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; + + case REQUEST_ACTION: + // if a result has been returned, display a notify + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; + + case REQUEST_VIEW_KEY: + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java new file mode 100644 index 000000000..b60003419 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2015 Adithya Abraham Philip + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Spinner; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.RevokeResult; +import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; + +public class RevokeDeleteDialogActivity extends FragmentActivity { + + public static final String EXTRA_MASTER_KEY_ID = "extra_master_key_id"; + public static final String EXTRA_KEYSERVER = "extra_keyserver"; + + private final int REVOKE_OP_ID = 1; + private final int DELETE_OP_ID = 2; + private CryptoOperationHelper mRevokeOpHelper; + private CryptoOperationHelper mDeleteOpHelper; + + private long mMasterKeyId; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mRevokeOpHelper = new CryptoOperationHelper<>(this, + getRevocationCallback(), R.string.progress_revoking_uploading, REVOKE_OP_ID); + mRevokeOpHelper.onRestoreInstanceState(savedInstanceState); + + mDeleteOpHelper = new CryptoOperationHelper<>(this, + getDeletionCallback(), R.string.progress_deleting, DELETE_OP_ID); + mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); + + mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, -1); + + RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(); + fragment.show(getSupportFragmentManager(), "deleteRevokeDialog"); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); + mRevokeOpHelper.handleActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mRevokeOpHelper.onSaveInstanceState(outState); + mDeleteOpHelper.onSaveInstanceState(outState); + } + + private void returnResult(OperationResult result) { + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, result); + setResult(RESULT_OK, intent); + finish(); + } + + private CryptoOperationHelper.Callback getRevocationCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public RevokeKeyringParcel createOperationInput() { + return new RevokeKeyringParcel(mMasterKeyId, true, + getIntent().getStringExtra(EXTRA_KEYSERVER)); + } + + @Override + public void onCryptoOperationSuccess(RevokeResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(RevokeResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; + } + + private CryptoOperationHelper.Callback getDeletionCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public DeleteKeyringParcel createOperationInput() { + return new DeleteKeyringParcel(new long[]{mMasterKeyId}, true); + } + + @Override + public void onCryptoOperationSuccess(DeleteResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(DeleteResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; + } + + private void startRevocationOperation() { + mRevokeOpHelper.cryptoOperation(); + } + + private void startDeletionOperation() { + mDeleteOpHelper.cryptoOperation(); + } + + public static class RevokeDeleteDialogFragment extends DialogFragment { + + public static RevokeDeleteDialogFragment newInstance() { + RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + + final String CHOICE_REVOKE = getString(R.string.del_rev_dialog_choice_rev_upload); + final String CHOICE_DELETE = getString(R.string.del_rev_dialog_choice_delete); + + // if the dialog is displayed from the application class, design is missing + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper theme = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); + alert.setTitle(R.string.del_rev_dialog_title); + + LayoutInflater inflater = LayoutInflater.from(theme); + View view = inflater.inflate(R.layout.del_rev_dialog, null); + alert.setView(view); + + final Spinner spinner = (Spinner) view.findViewById(R.id.spinner); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + activity.setResult(RESULT_CANCELED); + activity.finish(); + } + }); + + alert.setPositiveButton(R.string.del_rev_dialog_btn_revoke, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + String choice = spinner.getSelectedItem().toString(); + if (choice.equals(CHOICE_REVOKE)) { + ((RevokeDeleteDialogActivity) activity) + .startRevocationOperation(); + } else if (choice.equals(CHOICE_DELETE)) { + ((RevokeDeleteDialogActivity) activity) + .startDeletionOperation(); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + }); + + final AlertDialog alertDialog = alert.show(); + + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int pos, long id) { + + String choice = parent.getItemAtPosition(pos).toString(); + + if (choice.equals(CHOICE_REVOKE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_revoke); + } else if (choice.equals(CHOICE_DELETE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_delete); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + + public void onNothingSelected(AdapterView parent) { + } + }); + + return alertDialog; + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 9ed46d517..32b5c76b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -68,7 +68,6 @@ import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; @@ -85,7 +84,6 @@ import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; import java.util.ArrayList; - public class ViewKeyActivity extends BaseNfcActivity implements LoaderManager.LoaderCallbacks, CryptoOperationHelper.Callback { @@ -97,6 +95,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements static final int REQUEST_QR_FINGERPRINT = 1; static final int REQUEST_BACKUP = 2; static final int REQUEST_CERTIFY = 3; + static final int REQUEST_DELETE = 4; + static final int REQUEST_REVOKE_DELETE = 5; public static final String EXTRA_DISPLAY_RESULT = "display_result"; @@ -419,27 +419,24 @@ public class ViewKeyActivity extends BaseNfcActivity implements } private void deleteKey() { - new Handler().post(new Runnable() { - @Override - public void run() { - // Message is received after key is deleted - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.arg1 == MessageStatus.OKAY.ordinal()) { - setResult(RESULT_CANCELED); - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - new long[]{ mMasterKeyId }); - deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog"); - } - }); + if (mIsSecret && !mIsRevoked) { + Intent revokeDeleteIntent = new Intent(this, RevokeDeleteDialogActivity.class); + + revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_MASTER_KEY_ID, + mMasterKeyId); + revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_KEYSERVER, + Preferences.getPreferences(this).getPreferredKeyserver()); + + startActivityForResult(revokeDeleteIntent, REQUEST_REVOKE_DELETE); + + } else { + Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class); + + deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, + new long[]{mMasterKeyId}); + + startActivityForResult(deleteIntent, REQUEST_DELETE); + } } @Override @@ -487,6 +484,13 @@ public class ViewKeyActivity extends BaseNfcActivity implements } return; } + + case REQUEST_REVOKE_DELETE: + case REQUEST_DELETE: { + setResult(RESULT_OK, data); + finish(); + return; + } } super.onActivityResult(requestCode, resultCode, data); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index 91ea969d7..c03c301a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; +import org.sufficientlysecure.keychain.ui.RevokeDeleteDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -119,17 +120,13 @@ public class CryptoOperationHelper - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.operations.results.DeleteResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; -import org.sufficientlysecure.keychain.service.ServiceProgressHandler; -import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.HashMap; - -public class DeleteKeyDialogFragment extends DialogFragment - implements CryptoOperationHelper.Callback { - private static final String ARG_MESSENGER = "messenger"; - private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; - - public static final int MESSAGE_OKAY = 1; - public static final int MESSAGE_ERROR = 0; - - private TextView mMainMessage; - private View mInflateView; - - private Messenger mMessenger; - - // for CryptoOperationHelper.Callback - private long[] mMasterKeyIds; - private boolean mHasSecret; - private CryptoOperationHelper mDeleteOpHelper; - - /** - * Creates new instance of this delete file dialog fragment - */ - public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] masterKeyIds) { - DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); - Bundle args = new Bundle(); - - args.putParcelable(ARG_MESSENGER, messenger); - args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); - - frag.setArguments(args); - - return frag; - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mDeleteOpHelper != null) { - mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); - } - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final FragmentActivity activity = getActivity(); - mMessenger = getArguments().getParcelable(ARG_MESSENGER); - - final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); - - CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(activity); - - // Setup custom View to display in AlertDialog - LayoutInflater inflater = activity.getLayoutInflater(); - mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); - builder.setView(mInflateView); - - mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage); - - final boolean hasSecret; - - // If only a single key has been selected - if (masterKeyIds.length == 1) { - long masterKeyId = masterKeyIds[0]; - - try { - HashMap data = new ProviderHelper(activity).getUnifiedData( - masterKeyId, new String[]{ - KeyRings.USER_ID, - KeyRings.HAS_ANY_SECRET - }, new int[]{ - ProviderHelper.FIELD_TYPE_STRING, - ProviderHelper.FIELD_TYPE_INTEGER - } - ); - String name; - KeyRing.UserId mainUserId = KeyRing.splitUserId((String) data.get(KeyRings.USER_ID)); - if (mainUserId.name != null) { - name = mainUserId.name; - } else { - name = getString(R.string.user_id_no_name); - } - hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1; - - if (hasSecret) { - // show title only for secret key deletions, - // see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior - builder.setTitle(getString(R.string.title_delete_secret_key, name)); - mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name)); - } else { - mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name)); - } - } catch (ProviderHelper.NotFoundException e) { - dismiss(); - return null; - } - } else { - mMainMessage.setText(R.string.key_deletion_confirmation_multi); - hasSecret = false; - } - - builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - mMasterKeyIds = masterKeyIds; - mHasSecret = hasSecret; - - mDeleteOpHelper = new CryptoOperationHelper<> - (1, DeleteKeyDialogFragment.this, DeleteKeyDialogFragment.this, - R.string.progress_deleting); - mDeleteOpHelper.cryptoOperation(); - // do NOT dismiss here, it'll give - // OperationHelper a null fragmentManager - // dismiss(); - } - }); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - dismiss(); - } - }); - - return builder.show(); - } - - @Override - public DeleteKeyringParcel createOperationInput() { - return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); - } - - @Override - public void onCryptoOperationSuccess(DeleteResult result) { - handleResult(result); - } - - @Override - public void onCryptoOperationCancelled() { - - } - - @Override - public void onCryptoOperationError(DeleteResult result) { - handleResult(result); - } - - @Override - public boolean onCryptoSetProgress(String msg, int progress, int max) { - return false; - } - - public void handleResult(DeleteResult result) { - try { - Bundle data = new Bundle(); - data.putParcelable(OperationResult.EXTRA_RESULT, result); - Message msg = Message.obtain(); - msg.arg1 = ServiceProgressHandler.MessageStatus.OKAY.ordinal(); - msg.setData(data); - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "messenger error", e); - } - dismiss(); - } -} -- cgit v1.2.3