diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java | 172 |
1 files changed, 87 insertions, 85 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java index 232a39f86..de90d48fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java @@ -18,114 +18,116 @@ package org.sufficientlysecure.keychain.ui.base; -import android.app.Activity; + +import android.content.Context; import android.content.Intent; -import android.os.Bundle; -import android.os.Message; +import android.os.Parcelable; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.view.View; +import android.view.inputmethod.InputMethodManager; -import org.sufficientlysecure.keychain.operations.results.InputPendingResult; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.OperationResult; -import org.sufficientlysecure.keychain.service.ServiceProgressHandler; +import org.sufficientlysecure.keychain.service.KeychainService; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.ui.NfcOperationActivity; -import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; -/** - * All fragments executing crypto operations need to extend this class. +/** This is a base class for fragments which implement a cryptoOperation. + * + * Subclasses of this class can call the cryptoOperation method to execute an + * operation in KeychainService which takes a parcelable of type T as its input + * and returns an OperationResult of type S as a result. + * + * The input (of type T) is not given directly to the cryptoOperation method, + * but must be provided by the overriden createOperationInput method to be + * available upon request during execution of the cryptoOperation. + * + * After running cryptoOperation, one of the onCryptoOperation*() methods will + * be called, depending on the success status of the operation. The subclass + * must override at least onCryptoOperationSuccess to proceed after a + * successful operation. + * + * @see KeychainService + * */ -public abstract class CryptoOperationFragment extends Fragment { - - public static final int REQUEST_CODE_PASSPHRASE = 0x00008001; - public static final int REQUEST_CODE_NFC = 0x00008002; - - private void initiateInputActivity(RequiredInputParcel requiredInput) { - - switch (requiredInput.mType) { - case NFC_DECRYPT: - case NFC_SIGN: { - Intent intent = new Intent(getActivity(), NfcOperationActivity.class); - intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput); - startActivityForResult(intent, REQUEST_CODE_NFC); - return; - } - - case PASSPHRASE: - case PASSPHRASE_SYMMETRIC: { - Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class); - intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput); - startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); - return; - } - } +public abstract class CryptoOperationFragment<T extends Parcelable, S extends OperationResult> + extends Fragment implements CryptoOperationHelper.Callback<T, S> { - throw new RuntimeException("Unhandled pending result!"); + final private CryptoOperationHelper<T, S> mOperationHelper; + + public CryptoOperationFragment() { + mOperationHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_processing); } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_CANCELED) { - onCryptoOperationCancelled(); - return; - } + public CryptoOperationFragment(Integer initialProgressMsg) { + mOperationHelper = new CryptoOperationHelper<>(1, this, this, initialProgressMsg); + } - switch (requestCode) { - case REQUEST_CODE_PASSPHRASE: { - if (resultCode == Activity.RESULT_OK && data != null) { - CryptoInputParcel cryptoInput = - data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT); - cryptoOperation(cryptoInput); - return; - } - break; - } - - case REQUEST_CODE_NFC: { - if (resultCode == Activity.RESULT_OK && data != null) { - CryptoInputParcel cryptoInput = - data.getParcelableExtra(NfcOperationActivity.RESULT_DATA); - cryptoOperation(cryptoInput); - return; - } - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - } - } + public CryptoOperationFragment(int id, Integer initialProgressMsg) { + mOperationHelper = new CryptoOperationHelper<>(id, this, this, initialProgressMsg); } - public boolean handlePendingMessage(Message message) { + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mOperationHelper.handleActivityResult(requestCode, resultCode, data); + } - if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) { - Bundle data = message.getData(); + /** Starts execution of the cryptographic operation. + * + * During this process, the createOperationInput() method will be called, + * this input will be handed to KeychainService, where it is executed in + * the appropriate *Operation class. If the result is a PendingInputResult, + * it is handled accordingly. Otherwise, it is returned in one of the + * onCryptoOperation* callbacks. + */ + protected void cryptoOperation() { + mOperationHelper.cryptoOperation(); + } - OperationResult result = data.getParcelable(OperationResult.EXTRA_RESULT); - if (result == null || !(result instanceof InputPendingResult)) { - return false; - } + protected void cryptoOperation(CryptoInputParcel cryptoInput) { + mOperationHelper.cryptoOperation(cryptoInput); + } - InputPendingResult pendingResult = (InputPendingResult) result; - if (pendingResult.isPending()) { - RequiredInputParcel requiredInput = pendingResult.getRequiredInputParcel(); - initiateInputActivity(requiredInput); - return true; - } - } + @Override @Nullable + /** Creates input for the crypto operation. Called internally after the + * crypto operation is started by a call to cryptoOperation(). Silently + * cancels operation if this method returns null. */ + public abstract T createOperationInput(); + /** Returns false, indicating that we did not handle progress ourselves. */ + public boolean onCryptoSetProgress(String msg, int progress, int max) { return false; } - protected void cryptoOperation() { - cryptoOperation(new CryptoInputParcel()); + public void setProgressMessageResource(int id) { + mOperationHelper.setProgressMessageResource(id); + } + + @Override + /** Called when the cryptoOperation() was successful. No default behavior + * here, this should always be implemented by a subclass! */ + abstract public void onCryptoOperationSuccess(S result); + + @Override + abstract public void onCryptoOperationError(S result); + + @Override + public void onCryptoOperationCancelled() { } - protected abstract void cryptoOperation(CryptoInputParcel cryptoInput); + public void hideKeyboard() { + if (getActivity() == null) { + return; + } + InputMethodManager inputManager = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + + // check if no view has focus + View v = getActivity().getCurrentFocus(); + if (v == null) + return; - protected void onCryptoOperationCancelled() { - // Nothing to do here, in most cases + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); } } |