diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 75d94ae69..171267933 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -672,6 +672,9 @@ android:name=".ui.LogDisplayActivity" android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:label="@string/title_log_display" /> + 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 d3ec0f2cc..f395699a2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -145,7 +145,7 @@ public class EditKeyFragment extends NewCryptoOperationFragment(this) { + new OperationHelper(this, R.string.progress_building_key) { @Override public SaveKeyringParcel createOperationInput() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index f3c11a785..874128f95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -47,6 +47,8 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.operation.ImportOperationHelper; +import org.sufficientlysecure.keychain.util.operation.OperationHelper; import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import java.io.IOException; @@ -87,14 +89,14 @@ public class ImportKeysActivity extends BaseNfcActivity { private Fragment mTopFragment; private View mImportButton; - private Preferences.ProxyPrefs mProxyPrefs; + private Preferences.ProxyPrefs mProxyPrefs; // set only when an explicit proxy is to be used + + private OperationHelper mImportOperationHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mProxyPrefs = Preferences.getPreferences(this).getProxyPrefs(); - mImportButton = findViewById(R.id.import_import); mImportButton.setOnClickListener(new OnClickListener() { @Override @@ -111,6 +113,12 @@ public class ImportKeysActivity extends BaseNfcActivity { setContentView(R.layout.import_keys_activity); } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (mImportOperationHelper != null) mImportOperationHelper.handleActivityResult(requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + } + protected void handleActions(Bundle savedInstanceState, Intent intent) { String action = intent.getAction(); Bundle extras = intent.getExtras(); @@ -351,6 +359,8 @@ public class ImportKeysActivity extends BaseNfcActivity { public void loadCallback(final ImportKeysListFragment.LoaderState loaderState) { if (loaderState instanceof ImportKeysListFragment.CloudLoaderState) { + Preferences.ProxyPrefs proxyPrefs = + mProxyPrefs == null ? Preferences.getPreferences(this).getProxyPrefs() : mProxyPrefs; // do the tor check // this handle will set tor to be ignored whenever a message is received Runnable ignoreTor = new Runnable() { @@ -361,22 +371,15 @@ public class ImportKeysActivity extends BaseNfcActivity { mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); } }; - if (OrbotHelper.isOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, mProxyPrefs, this)) { - mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); + if (OrbotHelper.isOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, proxyPrefs, this)) { + mListFragment.loadNew(loaderState, proxyPrefs.parcelableProxy); } } else if (loaderState instanceof ImportKeysListFragment.BytesLoaderState) { // must always be true mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); } } - private void handleMessage(Message message) { - if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) { - // get returned data bundle - Bundle returnData = message.getData(); - if (returnData == null) { - return; - } - final ImportKeyResult result = returnData.getParcelable(OperationResult.EXTRA_RESULT); + private void handleResult(ImportKeyResult result) { if (result == null) { Log.e(Constants.TAG, "result == null"); return; @@ -398,7 +401,6 @@ public class ImportKeysActivity extends BaseNfcActivity { result.createNotify(ImportKeysActivity.this) .show((ViewGroup) findViewById(R.id.import_snackbar)); - } } /** @@ -412,20 +414,9 @@ public class ImportKeysActivity extends BaseNfcActivity { return; } - ServiceProgressHandler serviceHandler = new ServiceProgressHandler(this) { - @Override - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - ImportKeysActivity.this.handleMessage(message); - } - }; - - // Send all information needed to service to import key in other thread - Intent intent = new Intent(this, KeychainNewService.class); - ImportKeyringParcel operationInput = null; - CryptoInputParcel cryptoInput = null; + ArrayList keyList = null; + String keyserver = null; + CryptoInputParcel cryptoInput = new CryptoInputParcel(); ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState(); if (ls instanceof ImportKeysListFragment.BytesLoaderState) { @@ -444,9 +435,6 @@ public class ImportKeysActivity extends BaseNfcActivity { new ParcelableFileCache<>(this, "key_import.pcl"); cache.writeCache(selectedEntries); - operationInput = new ImportKeyringParcel(null, null); - cryptoInput = new CryptoInputParcel(); - } catch (IOException e) { Log.e(Constants.TAG, "Problem writing cache file", e); Notify.create(this, "Problem writing cache file!", Notify.Style.ERROR) @@ -456,40 +444,32 @@ public class ImportKeysActivity extends BaseNfcActivity { ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls; // get selected key entries - ArrayList keys = new ArrayList<>(); + keyList = new ArrayList<>(); { // change the format into ParcelableKeyRing ArrayList entries = mListFragment.getSelectedEntries(); for (ImportKeysListEntry entry : entries) { - keys.add(new ParcelableKeyRing( + keyList.add(new ParcelableKeyRing( entry.getFingerprintHex(), entry.getKeyIdHex(), entry.getExtraData()) ); } } - operationInput = new ImportKeyringParcel(keys, sls.mCloudPrefs.keyserver); + keyserver = sls.mCloudPrefs.keyserver; + if (mProxyPrefs != null) { // if not null means we have specified an explicit proxy cryptoInput = new CryptoInputParcel(mProxyPrefs.parcelableProxy); - } else { - cryptoInput = new CryptoInputParcel(); } } - intent.putExtra(KeychainNewService.EXTRA_OPERATION_INPUT, operationInput); - intent.putExtra(KeychainNewService.EXTRA_CRYPTO_INPUT, cryptoInput); + mImportOperationHelper = new ImportOperationHelper(this, R.string.progress_importing, keyList, keyserver) { + @Override + protected void onCryptoOperationSuccess(ImportKeyResult result) { + handleResult(result); + } + }; - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(serviceHandler); - intent.putExtra(KeychainService.EXTRA_MESSENGER, messenger); - - // show progress dialog - serviceHandler.showProgressDialog( - getString(R.string.progress_importing), - ProgressDialog.STYLE_HORIZONTAL, true - ); - - // start service with intent - startService(intent); + mImportOperationHelper.cryptoOperation(cryptoInput); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java index 25fab7938..117f2fef4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java @@ -18,10 +18,46 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.os.AsyncTask; import android.os.Bundle; +import android.os.Handler; +import android.os.Messenger; +import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; +import android.text.InputType; +import android.text.method.PasswordTransformationMethod; +import android.view.*; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.ui.dialog.OrbotStartDialogFragment; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; @@ -30,24 +66,40 @@ import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; */ public class OrbotRequiredDialogActivity extends FragmentActivity { - public final static String RESULT_IGNORE_TOR = "ignore_tor"; + public static final String RESULT_IGNORE_TOR = "result_ignore_tor"; @Override - public void onCreate(Bundle savedInstanceState) { - Runnable ignoreTor = new Runnable() { - @Override - public void run() { - Intent data = new Intent(); - data.putExtra(RESULT_IGNORE_TOR, true); - setResult(RESULT_OK, data); - } - }; + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + showDialog(); + } - if (OrbotHelper.isOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, - Preferences.getPreferences(this).getProxyPrefs(), this)) { - Intent data = new Intent(); - data.putExtra(RESULT_IGNORE_TOR, false); - setResult(RESULT_OK, data); - } + /** + * Shows passphrase dialog to cache a new passphrase the user enters for using it later for + * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks + * for a symmetric passphrase + */ + public void showDialog() { + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + Runnable ignoreTor = new Runnable() { + @Override + public void run() { + Intent intent = new Intent(); + intent.putExtra(RESULT_IGNORE_TOR, true); + setResult(RESULT_OK, intent); + finish(); + } + }; + if (OrbotHelper.isOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, + OrbotRequiredDialogActivity.this)) { + // no action required after all + Intent intent = new Intent(); + intent.putExtra(RESULT_IGNORE_TOR, true); + setResult(RESULT_OK, intent); + finish(); + } + } + }); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java index 4736eddca..4da2db15d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui.dialog; +import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; @@ -26,6 +27,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; +import android.view.ContextThemeWrapper; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; @@ -62,8 +64,14 @@ public class OrbotStartDialogFragment extends DialogFragment { int title = getArguments().getInt(ARG_TITLE); final int message = getArguments().getInt(ARG_MESSAGE); int middleButton = getArguments().getInt(ARG_MIDDLE_BUTTON); + final Activity activity = getActivity(); - CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); + // 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 builder = new CustomAlertDialogBuilder(theme); builder.setTitle(title).setMessage(message); builder.setNegativeButton(R.string.orbot_start_dialog_cancel, new DialogInterface.OnClickListener() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java index 4898e7f1a..36d9564dd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java @@ -68,6 +68,10 @@ public class ParcelableProxy implements Parcelable { return new Proxy(type, new InetSocketAddress(mProxyHost, mProxyPort)); } + public static ParcelableProxy getForNoProxy() { + return new ParcelableProxy(null, -1, null); + } + protected ParcelableProxy(Parcel in) { mProxyHost = in.readString(); mProxyPort = in.readInt(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/ImportOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/ImportOperationHelper.java index 7b3af0af5..4c3747f47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/ImportOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/ImportOperationHelper.java @@ -29,8 +29,9 @@ public abstract class ImportOperationHelper extends OperationHelper mKeyList; private String mKeyserver; - public ImportOperationHelper(FragmentActivity activity, ArrayList keyList, String keyserver) { - super(activity); + public ImportOperationHelper(FragmentActivity activity, int progressMessageString, + ArrayList keyList, String keyserver) { + super(activity, progressMessageString); mKeyList = keyList; mKeyserver = keyserver; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/OperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/OperationHelper.java index 1f7e1bbd4..7587d86c8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/OperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/operation/OperationHelper.java @@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ParcelableProxy; /** * Designed to be intergrated into activities or fragments used for CryptoOperations. @@ -54,6 +55,8 @@ public abstract class OperationHelper