aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java35
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DisplayTextFragment.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java30
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java31
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java91
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java209
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java28
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CachingCryptoOperationFragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java75
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java129
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java75
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SupportInstallDialogFragment.java76
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/InstallDialogFragmentHelper.java135
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java2
32 files changed, 1083 insertions, 164 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
index 891c2268c..ab631c6fe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -311,6 +312,11 @@ public class CertifyKeyFragment
CertifyActionsParcel actionsParcel = new CertifyActionsParcel(selectedKeyId);
actionsParcel.mCertifyActions.addAll(certifyActions);
+ if (mUploadKeyCheckbox.isChecked()) {
+ actionsParcel.keyServerUri = Preferences.getPreferences(getActivity())
+ .getPreferredKeyserver();
+ }
+
// cached for next cryptoOperation loop
cacheActionsParcel(actionsParcel);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
index 7192b7335..51c1bd079 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -385,14 +386,18 @@ public class CreateKeyFinalFragment extends Fragment {
}
public void handleResult(ExportResult result) {
- // TODO: ExportOperation UPLOAD_KEYSERVER needs logs!
- // TODO: then merge logs here!
- //saveKeyResult.getLog().add(result, 0);
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ saveKeyResult.getLog().add(result, 0);
Intent data = new Intent();
data.putExtra(OperationResult.EXTRA_RESULT, saveKeyResult);
- getActivity().setResult(Activity.RESULT_OK, data);
- getActivity().finish();
+ activity.setResult(Activity.RESULT_OK, data);
+ activity.finish();
+
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
index c64f05687..9e3dce28f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
@@ -41,7 +41,9 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.NfcListenerFragment;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
public class CreateYubiKeyImportFragment
@@ -131,7 +133,18 @@ public class CreateYubiKeyImportFragment
view.findViewById(R.id.button_search).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- refreshSearch();
+ final Preferences.ProxyPrefs proxyPrefs = Preferences.getPreferences(getActivity()).getProxyPrefs();
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ refreshSearch(new ParcelableProxy(null, -1, null));
+ }
+ };
+
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, proxyPrefs,
+ getActivity())) {
+ refreshSearch(proxyPrefs.parcelableProxy);
+ }
}
});
@@ -170,9 +183,10 @@ public class CreateYubiKeyImportFragment
}
}
- public void refreshSearch() {
+ public void refreshSearch(ParcelableProxy parcelableProxy) {
+ // TODO: PHILIP verify proxy implementation in YubiKey parts
mListFragment.loadNew(new ImportKeysListFragment.CloudLoaderState("0x" + mNfcFingerprint,
- Preferences.getPreferences(getActivity()).getCloudSearchPrefs()));
+ Preferences.getPreferences(getActivity()).getCloudSearchPrefs()), parcelableProxy);
}
public void importKey() {
@@ -210,7 +224,20 @@ public class CreateYubiKeyImportFragment
public void onNfcPostExecute() throws IOException {
setData();
- refreshSearch();
+
+ Preferences.ProxyPrefs proxyPrefs = Preferences.getPreferences(getActivity()).getProxyPrefs();
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ refreshSearch(new ParcelableProxy(null, -1, null));
+ }
+ };
+
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, proxyPrefs,
+ getActivity())) {
+ refreshSearch(proxyPrefs.parcelableProxy);
+ }
+
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 4eb8cd5e8..afd6b337e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -19,15 +19,11 @@ package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
-import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Message;
-import android.os.Messenger;
import android.support.v4.app.Fragment;
-import android.os.Parcelable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
@@ -52,13 +48,14 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
-import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
public abstract class DecryptFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
index 96767463e..db2841488 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
@@ -304,7 +304,7 @@ public class DecryptListFragment
}
final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setType(type);
+ intent.setDataAndType(outputUri, type);
final List<ResolveInfo> matches =
context.getPackageManager().queryIntentActivities(intent, 0);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DisplayTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DisplayTextFragment.java
index 7b3af48cc..dc06e9115 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DisplayTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DisplayTextFragment.java
@@ -17,6 +17,10 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -29,9 +33,9 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.ShareHelper;
public class DisplayTextFragment extends DecryptFragment {
@@ -80,8 +84,19 @@ public class DisplayTextFragment extends DecryptFragment {
}
private void copyToClipboard(String text) {
- ClipboardReflection.copyToClipboard(getActivity(), text);
- Notify.create(getActivity(), R.string.text_copied_to_clipboard, Notify.Style.OK).show();
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ ClipboardManager clipMan = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (clipMan == null) {
+ Notify.create(activity, R.string.error_clipboard_copy, Style.ERROR).show();
+ return;
+ }
+
+ clipMan.setPrimaryClip(ClipData.newPlainText(Constants.CLIPBOARD_LABEL, text));
+ Notify.create(activity, R.string.text_copied_to_clipboard, Style.OK).show();
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
index 779b22535..fc72a6c9f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
@@ -124,8 +124,7 @@ public class EncryptDecryptOverviewFragment extends Fragment {
super.onResume();
// get text from clipboard
- final CharSequence clipboardText =
- ClipboardReflection.getClipboardText(getActivity());
+ final CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
// if it's null, nothing to do here /o/
if (clipboardText == null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index 215af5885..b382e31d0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -35,6 +35,7 @@ import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -388,6 +389,12 @@ public class EncryptFilesFragment
@Override
public void onCryptoOperationSuccess(final SignEncryptResult result) {
+ FragmentActivity activity = getActivity();
+ if (activity == null) {
+ // it's gone, there's nothing we can do here
+ return;
+ }
+
if (mDeleteAfterEncrypt) {
// TODO make behavior coherent here
DeleteFileDialogFragment deleteFileDialog =
@@ -400,13 +407,18 @@ public class EncryptFilesFragment
// Share encrypted message/file
startActivity(sendWithChooserExcludingEncrypt());
} else {
+ Activity activity = getActivity();
+ if (activity == null) {
+ // it's gone, there's nothing we can do here
+ return;
+ }
// Save encrypted file
- result.createNotify(getActivity()).show();
+ result.createNotify(activity).show();
}
}
});
- deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
+ deleteFileDialog.show(activity.getSupportFragmentManager(), "deleteDialog");
} else {
switch (mAfterEncryptAction) {
@@ -417,25 +429,24 @@ public class EncryptFilesFragment
break;
case COPY:
- Activity activity = getActivity();
- if (activity == null) {
- // it's gone, there's nothing we can do here
- return;
- }
ClipboardManager clipMan = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (clipMan == null) {
+ Notify.create(activity, R.string.error_clipboard_copy, Style.ERROR).show();
+ break;
+ }
ClipData clip = new ClipData(getString(R.string.label_clip_title),
// make available as application/pgp-encrypted
new String[] { "text/plain" },
new ClipData.Item(mOutputUris.get(0))
);
clipMan.setPrimaryClip(clip);
- result.createNotify(getActivity()).show();
+ result.createNotify(activity).show();
break;
case SAVE:
// Encrypted file was saved already, just show notification
- result.createNotify(getActivity()).show();
+ result.createNotify(activity).show();
break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
index 886c52651..8d3738fbd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
@@ -18,6 +18,9 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
@@ -33,7 +36,6 @@ import android.widget.TextView;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
@@ -265,8 +267,21 @@ public class EncryptTextFragment
return data;
}
- private void copyToClipboard(byte[] resultBytes) {
- ClipboardReflection.copyToClipboard(getActivity(), new String(resultBytes));
+ private void copyToClipboard(SignEncryptResult result) {
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ ClipboardManager clipMan = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (clipMan == null) {
+ Notify.create(activity, R.string.error_clipboard_copy, Style.ERROR).show();
+ return;
+ }
+
+ ClipData clip = ClipData.newPlainText(Constants.CLIPBOARD_LABEL, new String(result.getResultBytes()));
+ clipMan.setPrimaryClip(clip);
+ result.createNotify(activity).show();
}
/**
@@ -323,11 +338,7 @@ public class EncryptTextFragment
startActivity(sendWithChooserExcludingEncrypt(result.getResultBytes()));
} else {
// Copy to clipboard
- copyToClipboard(result.getResultBytes());
- result.createNotify(getActivity()).show();
- // Notify.create(EncryptTextActivity.this,
- // R.string.encrypt_sign_clipboard_successful, Notify.Style.OK)
- // .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
+ copyToClipboard(result);
}
}
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 bc83b05b0..2e8e6f6bd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -42,6 +42,8 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
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.orbot.OrbotHelper;
import java.io.IOException;
import java.util.ArrayList;
@@ -87,11 +89,14 @@ public class ImportKeysActivity extends BaseNfcActivity
private ArrayList<ParcelableKeyRing> mKeyList;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mOperationHelper;
+ private Preferences.ProxyPrefs mProxyPrefs;
@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
@@ -224,7 +229,7 @@ public class ImportKeysActivity extends BaseNfcActivity
Notify.Style.WARN).show(mTopFragment);
// we just set the keyserver
startCloudFragment(savedInstanceState, null, false, keyserver);
- // it's not necessary to set the keyserver for ImportKeysListFragment since
+ // we don't set the keyserver for ImportKeysListFragment since
// it'll be taken care of by ImportKeysCloudFragment when the user clicks
// the search button
startListFragment(savedInstanceState, null, null, null, null);
@@ -316,7 +321,8 @@ public class ImportKeysActivity extends BaseNfcActivity
* specified in user preferences
*/
- private void startCloudFragment(Bundle savedInstanceState, String query, boolean disableQueryEdit, String keyserver) {
+ private void startCloudFragment(Bundle savedInstanceState, String query, boolean disableQueryEdit, String
+ keyserver) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
@@ -346,8 +352,24 @@ public class ImportKeysActivity extends BaseNfcActivity
}
}
- public void loadCallback(ImportKeysListFragment.LoaderState loaderState) {
- mListFragment.loadNew(loaderState);
+ public void loadCallback(final ImportKeysListFragment.LoaderState loaderState) {
+ if (loaderState instanceof ImportKeysListFragment.CloudLoaderState) {
+ // do the tor check
+ // this handle will set tor to be ignored whenever a message is received
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ // disables Tor until Activity is recreated
+ mProxyPrefs = new Preferences.ProxyPrefs(false, false, null, -1, null);
+ mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy);
+ }
+ };
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, mProxyPrefs, this)) {
+ mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy);
+ }
+ } else if (loaderState instanceof ImportKeysListFragment.BytesLoaderState) { // must always be true
+ mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy);
+ }
}
private void handleMessage(Message message) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index bf7e41045..55ccc3975 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
import java.io.ByteArrayInputStream;
@@ -64,6 +65,7 @@ public class ImportKeysListFragment extends ListFragment implements
private ImportKeysAdapter mAdapter;
private LoaderState mLoaderState;
+ private ParcelableProxy mProxy;
private static final int LOADER_ID_BYTES = 0;
private static final int LOADER_ID_CLOUD = 1;
@@ -126,6 +128,7 @@ public class ImportKeysListFragment extends ListFragment implements
/**
* Creates an interactive ImportKeyListFragment which reads keyrings from bytes, or file specified
* by dataUri, or searches a keyserver for serverQuery, if parameter is not null, in that order
+ * Will immediately load data if non-null bytes/dataUri/serverQuery
*
* @param bytes byte data containing list of keyrings to be imported
* @param dataUri file from which keyrings are to be imported
@@ -141,7 +144,7 @@ public class ImportKeysListFragment extends ListFragment implements
/**
* Visually consists of a list of keyrings with checkboxes to specify which are to be imported
- * Can immediately load keyrings specified by any of its parameters
+ * Will immediately load data if non-null bytes/dataUri/serverQuery is supplied
*
* @param bytes byte data containing list of keyrings to be imported
* @param dataUri file from which keyrings are to be imported
@@ -258,7 +261,9 @@ public class ImportKeysListFragment extends ListFragment implements
mAdapter.notifyDataSetChanged();
}
- public void loadNew(LoaderState loaderState) {
+ public void loadNew(LoaderState loaderState, ParcelableProxy proxy) {
+ mProxy = proxy;
+
mLoaderState = loaderState;
restartLoaders();
@@ -301,7 +306,7 @@ public class ImportKeysListFragment extends ListFragment implements
}
case LOADER_ID_CLOUD: {
CloudLoaderState ls = (CloudLoaderState) mLoaderState;
- return new ImportKeysListCloudLoader(getActivity(), ls.mServerQuery, ls.mCloudPrefs);
+ return new ImportKeysListCloudLoader(getActivity(), ls.mServerQuery, ls.mCloudPrefs, mProxy);
}
default:
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index da713d0d8..f45f1b350 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -44,7 +44,9 @@ import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList;
import java.util.Locale;
@@ -157,8 +159,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
returnResult(intent);
return;
}
-
- String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
+ final String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
if (!fingerprint.matches("[a-fA-F0-9]{40}")) {
SingletonResult result = new SingletonResult(
SingletonResult.RESULT_ERROR, LogType.MSG_WRONG_QR_CODE_FP);
@@ -273,7 +274,8 @@ public class ImportKeysProxyActivity extends FragmentActivity
// only one message sent during the beam
NdefMessage msg = (NdefMessage) rawMsgs[0];
// record 0 contains the MIME type, record 1 is the AAR, if present
- byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
+ final byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
+
importKeys(receivedKeyringBytes);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index e038cf948..c5bfdbedf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -52,6 +52,9 @@ import android.widget.TextView;
import com.getbase.floatingactionbutton.FloatingActionButton;
import com.getbase.floatingactionbutton.FloatingActionsMenu;
+import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
+import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
@@ -71,19 +74,16 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.FabContainer;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
-import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
-import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
-
/**
* Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
* StickyListHeaders library which does not extend upon ListView.
@@ -478,10 +478,6 @@ public class KeyListFragment extends LoaderFragment
updateAllKeys();
return true;
- case R.id.menu_key_list_debug_cons:
- consolidate();
- return true;
-
case R.id.menu_key_list_debug_read:
try {
KeychainDatabase.debugBackup(getActivity(), true);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
index ec6fd1bbe..51ed2b012 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
@@ -128,6 +128,11 @@ public class MainActivity extends BaseNfcActivity implements FabContainer, OnBac
getSupportFragmentManager().addOnBackStackChangedListener(this);
+ // all further initialization steps are saved as instance state
+ if (savedInstanceState != null) {
+ return;
+ }
+
Intent data = getIntent();
// If we got an EXTRA_RESULT in the intent, show the notification
if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
@@ -135,20 +140,18 @@ public class MainActivity extends BaseNfcActivity implements FabContainer, OnBac
result.createNotify(this).show();
}
- if (savedInstanceState == null) {
- // always initialize keys fragment to the bottom of the backstack
- onKeysSelected();
-
- if (data != null && data.hasExtra(EXTRA_INIT_FRAG)) {
- // initialize FragmentLayout with KeyListFragment at first
- switch (data.getIntExtra(EXTRA_INIT_FRAG, -1)) {
- case ID_ENCRYPT_DECRYPT:
- onEnDecryptSelected();
- break;
- case ID_APPS:
- onAppsSelected();
- break;
- }
+ // always initialize keys fragment to the bottom of the backstack
+ onKeysSelected();
+
+ if (data != null && data.hasExtra(EXTRA_INIT_FRAG)) {
+ // initialize FragmentLayout with KeyListFragment at first
+ switch (data.getIntExtra(EXTRA_INIT_FRAG, -1)) {
+ case ID_ENCRYPT_DECRYPT:
+ onEnDecryptSelected();
+ break;
+ case ID_APPS:
+ onAppsSelected();
+ break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
new file mode 100644
index 000000000..587044659
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
+import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
+
+/**
+ * Simply encapsulates a dialog. If orbot is not installed, it shows an install dialog, else a
+ * dialog to enable orbot.
+ */
+public class OrbotRequiredDialogActivity extends FragmentActivity {
+
+ // to provide any previous crypto input into which proxy preference is merged
+ public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input";
+
+ public static final String RESULT_CRYPTO_INPUT = "result_crypto_input";
+
+ private CryptoInputParcel mCryptoInputParcel;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
+ if (mCryptoInputParcel == null) {
+ mCryptoInputParcel = new CryptoInputParcel();
+ }
+ showDialog();
+ }
+
+ /**
+ * Displays an install or start orbot dialog depending on orbot's presence and state
+ */
+ public void showDialog() {
+ DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
+ public void run() {
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ Intent intent = new Intent();
+ mCryptoInputParcel.addParcelableProxy(ParcelableProxy.getForNoProxy());
+ intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+ };
+
+ Runnable dialogDismissed = new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ };
+
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, dialogDismissed,
+ Preferences.getPreferences(OrbotRequiredDialogActivity.this)
+ .getProxyPrefs(),
+ OrbotRequiredDialogActivity.this)) {
+ // no action required after all
+ Intent intent = new Intent();
+ intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
+ setResult(RESULT_OK, intent);
+ }
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
index 2e838535d..ed96156fe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
@@ -43,7 +43,9 @@ 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.util.Log;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -207,7 +209,7 @@ public class PassphraseWizardActivity extends FragmentActivity {
// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
}
} catch (IOException | FormatException e) {
- e.printStackTrace();
+ Log.e(Constants.TAG, "Failed to write on NFC tag", e);
}
} else if (readNFC && AUTHENTICATION.equals(selectedAction)) {
@@ -232,7 +234,7 @@ public class PassphraseWizardActivity extends FragmentActivity {
}
}
} catch (IOException | FormatException e) {
- e.printStackTrace();
+ Log.e(Constants.TAG, "Failed to read NFC tag", e);
}
}
}
@@ -263,7 +265,7 @@ public class PassphraseWizardActivity extends FragmentActivity {
try {
password = readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
- e.printStackTrace();
+ Log.e(Constants.TAG, "Failed to read password from tag", e);
}
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index 6fc0aaac6..f72a552d5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -18,14 +18,21 @@
package org.sufficientlysecure.keychain.ui;
+import android.annotation.TargetApi;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
import android.preference.Preference;
+import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.support.v7.widget.Toolbar;
+import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
@@ -33,9 +40,11 @@ import android.widget.LinearLayout;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.AppCompatPreferenceActivity;
+import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.List;
@@ -43,6 +52,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
public static final String ACTION_PREFS_CLOUD = "org.sufficientlysecure.keychain.ui.PREFS_CLOUD";
public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
+ public static final String ACTION_PREFS_PROXY = "org.sufficientlysecure.keychain.ui.PREFS_PROXY";
public static final int REQUEST_CODE_KEYSERVER_PREF = 0x00007005;
@@ -209,9 +219,205 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
}
+ public static class ProxyPrefsFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ new Initializer(this).initialize();
+
+ }
+
+ public static class Initializer {
+ private CheckBoxPreference mUseTor;
+ private CheckBoxPreference mUseNormalProxy;
+ private EditTextPreference mProxyHost;
+ private EditTextPreference mProxyPort;
+ private ListPreference mProxyType;
+ private PreferenceActivity mActivity;
+ private PreferenceFragment mFragment;
+
+ public Initializer(PreferenceFragment fragment) {
+ mFragment = fragment;
+ }
+
+ public Initializer(PreferenceActivity activity) {
+ mActivity = activity;
+ }
+
+ public Preference automaticallyFindPreference(String key) {
+ if (mFragment != null) {
+ return mFragment.findPreference(key);
+ } else {
+ return mActivity.findPreference(key);
+ }
+ }
+
+ public void initialize() {
+ // makes android's preference framework write to our file instead of default
+ // This allows us to use the "persistent" attribute to simplify code
+ if (mFragment != null) {
+ Preferences.setPreferenceManagerFileAndMode(mFragment.getPreferenceManager());
+ // Load the preferences from an XML resource
+ mFragment.addPreferencesFromResource(R.xml.proxy_prefs);
+ } else {
+ Preferences.setPreferenceManagerFileAndMode(mActivity.getPreferenceManager());
+ // Load the preferences from an XML resource
+ mActivity.addPreferencesFromResource(R.xml.proxy_prefs);
+ }
+
+ mUseTor = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY);
+ mUseNormalProxy = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY);
+ mProxyHost = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_HOST);
+ mProxyPort = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_PORT);
+ mProxyType = (ListPreference) automaticallyFindPreference(Constants.Pref.PROXY_TYPE);
+ initializeUseTorPref();
+ initializeUseNormalProxyPref();
+ initializeEditTextPreferences();
+ initializeProxyTypePreference();
+
+ if (mUseTor.isChecked()) disableNormalProxyPrefs();
+ else if (mUseNormalProxy.isChecked()) disableUseTorPrefs();
+ }
+
+ private void initializeUseTorPref() {
+ mUseTor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ if ((Boolean) newValue) {
+ boolean installed = OrbotHelper.isOrbotInstalled(activity);
+ if (!installed) {
+ Log.d(Constants.TAG, "Prompting to install Tor");
+ OrbotHelper.getPreferenceInstallDialogFragment().show(activity.getFragmentManager(),
+ "installDialog");
+ // don't let the user check the box until he's installed orbot
+ return false;
+ } else {
+ disableNormalProxyPrefs();
+ // let the enable tor box be checked
+ return true;
+ }
+ } else {
+ // we're unchecking Tor, so enable other proxy
+ enableNormalProxyPrefs();
+ return true;
+ }
+ }
+ });
+ }
+
+ private void initializeUseNormalProxyPref() {
+ mUseNormalProxy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if ((Boolean) newValue) {
+ disableUseTorPrefs();
+ } else {
+ enableUseTorPrefs();
+ }
+ return true;
+ }
+ });
+ }
+
+ private void initializeEditTextPreferences() {
+ mProxyHost.setSummary(mProxyHost.getText());
+ mProxyPort.setSummary(mProxyPort.getText());
+
+ mProxyHost.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ if (TextUtils.isEmpty((String) newValue)) {
+ Notify.create(
+ activity,
+ R.string.pref_proxy_host_err_invalid,
+ Notify.Style.ERROR
+ ).show();
+ return false;
+ } else {
+ mProxyHost.setSummary((CharSequence) newValue);
+ return true;
+ }
+ }
+ });
+
+ mProxyPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ try {
+ int port = Integer.parseInt((String) newValue);
+ if (port < 0 || port > 65535) {
+ Notify.create(
+ activity,
+ R.string.pref_proxy_port_err_invalid,
+ Notify.Style.ERROR
+ ).show();
+ return false;
+ }
+ // no issues, save port
+ mProxyPort.setSummary("" + port);
+ return true;
+ } catch (NumberFormatException e) {
+ Notify.create(
+ activity,
+ R.string.pref_proxy_port_err_invalid,
+ Notify.Style.ERROR
+ ).show();
+ return false;
+ }
+ }
+ });
+ }
+
+ private void initializeProxyTypePreference() {
+ mProxyType.setSummary(mProxyType.getEntry());
+
+ mProxyType.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ CharSequence entry = mProxyType.getEntries()[mProxyType.findIndexOfValue((String) newValue)];
+ mProxyType.setSummary(entry);
+ return true;
+ }
+ });
+ }
+
+ private void disableNormalProxyPrefs() {
+ mUseNormalProxy.setChecked(false);
+ mUseNormalProxy.setEnabled(false);
+ mProxyHost.setEnabled(false);
+ mProxyPort.setEnabled(false);
+ mProxyType.setEnabled(false);
+ }
+
+ private void enableNormalProxyPrefs() {
+ mUseNormalProxy.setEnabled(true);
+ mProxyHost.setEnabled(true);
+ mProxyPort.setEnabled(true);
+ mProxyType.setEnabled(true);
+ }
+
+ private void disableUseTorPrefs() {
+ mUseTor.setChecked(false);
+ mUseTor.setEnabled(false);
+ }
+
+ private void enableUseTorPrefs() {
+ mUseTor.setEnabled(true);
+ }
+ }
+
+ }
+
+ @TargetApi(Build.VERSION_CODES.KITKAT)
protected boolean isValidFragment(String fragmentName) {
return AdvancedPrefsFragment.class.getName().equals(fragmentName)
|| CloudSearchPrefsFragment.class.getName().equals(fragmentName)
+ || ProxyPrefsFragment.class.getName().equals(fragmentName)
|| super.isValidFragment(fragmentName);
}
@@ -270,7 +476,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
String[] servers = sPreferences.getKeyServers();
String serverSummary = context.getResources().getQuantityString(
R.plurals.n_keyservers, servers.length, servers.length);
- return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences.getPreferredKeyserver();
+ return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences
+ .getPreferredKeyserver();
}
private static void initializeUseDefaultYubiKeyPin(final CheckBoxPreference mUseDefaultYubiKeyPin) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
index 8b49f3b96..703a85b0f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
@@ -26,7 +26,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
-import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -38,6 +37,7 @@ import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
/**
* Sends the selected public key to a keyserver
@@ -132,8 +132,7 @@ public class UploadKeyActivity extends BaseActivity
@Override
public void onCryptoOperationSuccess(ExportResult result) {
- Toast.makeText(UploadKeyActivity.this, R.string.msg_crt_upload_success,
- Toast.LENGTH_SHORT).show();
+ result.createNotify(this).show();
}
@Override
@@ -143,7 +142,7 @@ public class UploadKeyActivity extends BaseActivity
@Override
public void onCryptoOperationError(ExportResult result) {
- // TODO: Implement proper log for key upload then show error
+ result.createNotify(this).show();
}
@Override
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 27832b665..ce8935bce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -84,7 +84,9 @@ import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.io.IOException;
import java.util.ArrayList;
@@ -464,11 +466,11 @@ public class ViewKeyActivity extends BaseNfcActivity implements
HashMap<String, Object> data = providerHelper.getGenericData(
baseUri,
- new String[] {KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
- new int[] {ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
+ new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
+ new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
exportHelper.showExportKeysDialog(
- new long[] {(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
+ new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
);
} catch (ProviderHelper.NotFoundException e) {
@@ -492,7 +494,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
- new long[] {mMasterKeyId});
+ new long[]{mMasterKeyId});
deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
}
@@ -636,7 +638,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
long keyId = new ProviderHelper(this)
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
- long[] encryptionKeyIds = new long[] {keyId};
+ long[] encryptionKeyIds = new long[]{keyId};
Intent intent;
if (text) {
intent = new Intent(this, EncryptTextActivity.class);
@@ -742,7 +744,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
// These are the rows that we will retrieve.
- static final String[] PROJECTION = new String[] {
+ static final String[] PROJECTION = new String[]{
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
@@ -830,7 +832,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements
AsyncTask<Long, Void, Bitmap> photoTask =
new AsyncTask<Long, Void, Bitmap>() {
protected Bitmap doInBackground(Long... mMasterKeyId) {
- return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), mMasterKeyId[0], true);
+ return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(),
+ mMasterKeyId[0], true);
}
protected void onPostExecute(Bitmap photo) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index b44e6dc78..f46b30137 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -25,6 +25,9 @@ import java.io.OutputStreamWriter;
import android.app.Activity;
import android.app.ActivityOptions;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -49,7 +52,6 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
@@ -58,6 +60,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
@@ -197,7 +200,15 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
}
if (toClipboard) {
- ClipboardReflection.copyToClipboard(activity, content);
+ ClipboardManager clipMan = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (clipMan == null) {
+ Notify.create(activity, R.string.error_clipboard_copy, Style.ERROR);
+ return;
+ }
+
+ ClipData clip = ClipData.newPlainText(Constants.CLIPBOARD_LABEL, content);
+ clipMan.setPrimaryClip(clip);
+
Notify.create(activity, fingerprintOnly ? R.string.fingerprint_copied_to_clipboard
: R.string.key_copied_to_clipboard, Notify.Style.OK).show();
return;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
index 6052eec16..40cbba5b3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
@@ -51,6 +51,9 @@ import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
+import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList;
import java.util.Hashtable;
@@ -197,8 +200,22 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
mStartSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- mStartSearch.setEnabled(false);
- new DescribeKey().execute(fingerprint);
+ final Preferences.ProxyPrefs proxyPrefs = Preferences.getPreferences(getActivity())
+ .getProxyPrefs();
+
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ mStartSearch.setEnabled(false);
+ new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
+ }
+ };
+
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, proxyPrefs,
+ getActivity())) {
+ mStartSearch.setEnabled(false);
+ new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
+ }
}
});
}
@@ -229,6 +246,11 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
// look for evidence from keybase in the background, make tabular version of result
//
private class DescribeKey extends AsyncTask<String, Void, ResultPage> {
+ ParcelableProxy mParcelableProxy;
+
+ public DescribeKey(ParcelableProxy parcelableProxy) {
+ mParcelableProxy = parcelableProxy;
+ }
@Override
protected ResultPage doInBackground(String... args) {
@@ -237,7 +259,7 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
final ArrayList<CharSequence> proofList = new ArrayList<CharSequence>();
final Hashtable<Integer, ArrayList<Proof>> proofs = new Hashtable<Integer, ArrayList<Proof>>();
try {
- User keybaseUser = User.findByFingerprint(fingerprint);
+ User keybaseUser = User.findByFingerprint(fingerprint, mParcelableProxy.getProxy());
for (Proof proof : keybaseUser.getProofs()) {
Integer proofType = proof.getType();
appendIfOK(proofs, proofType, proof);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
index f8c3b59ea..c2158650b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
@@ -210,7 +210,7 @@ public class ViewKeyYubiKeyFragment
}
@Override
- protected void onCryptoOperationResult(PromoteKeyResult result) {
+ public void onCryptoOperationSuccess(PromoteKeyResult result) {
result.createNotify(getActivity()).show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
index af919f3b6..c7f69207c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
@@ -27,6 +27,7 @@ import org.sufficientlysecure.keychain.keyimport.Keyserver;
import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -38,15 +39,18 @@ public class ImportKeysListCloudLoader
Preferences.CloudSearchPrefs mCloudPrefs;
String mServerQuery;
+ private ParcelableProxy mParcelableProxy;
private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
- public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs) {
+ public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs,
+ ParcelableProxy proxy) {
super(context);
mContext = context;
mServerQuery = serverQuery;
mCloudPrefs = cloudPrefs;
+ mParcelableProxy = proxy;
}
@Override
@@ -96,8 +100,11 @@ public class ImportKeysListCloudLoader
*/
private void queryServer(boolean enforceFingerprint) {
try {
- ArrayList<ImportKeysListEntry> searchResult
- = CloudSearch.search(mServerQuery, mCloudPrefs);
+ ArrayList<ImportKeysListEntry> searchResult = CloudSearch.search(
+ mServerQuery,
+ mCloudPrefs,
+ mParcelableProxy.getProxy()
+ );
mEntryList.clear();
// add result to data
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CachingCryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CachingCryptoOperationFragment.java
index 17e4e6ede..95bc4adcb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CachingCryptoOperationFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CachingCryptoOperationFragment.java
@@ -31,8 +31,12 @@ public abstract class CachingCryptoOperationFragment <T extends Parcelable, S ex
}
@Override
- protected void onCryptoOperationResult(S result) {
- super.onCryptoOperationResult(result);
+ public void onCryptoOperationSuccess(S result) {
+ mCachedActionsParcel = null;
+ }
+
+ @Override
+ public void onCryptoOperationError(S result) {
mCachedActionsParcel = null;
}
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 115f52d56..2ab0d5fac 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
@@ -20,56 +20,88 @@ package org.sufficientlysecure.keychain.ui.base;
import android.content.Intent;
import android.os.Parcelable;
+import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.service.KeychainService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-/**
- * 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<T extends Parcelable, S extends OperationResult>
extends Fragment implements CryptoOperationHelper.Callback<T, S> {
- private CryptoOperationHelper<T, S> mOperationHelper;
+ final private CryptoOperationHelper<T, S> mOperationHelper;
public CryptoOperationFragment() {
mOperationHelper = new CryptoOperationHelper<>(this, this);
}
- public void setProgressMessageResource(int id) {
- mOperationHelper.setProgressMessageResource(id);
- }
-
-
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mOperationHelper.handleActivityResult(requestCode, resultCode, data);
}
- @Override
- public abstract T createOperationInput();
-
+ /** 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() {
- cryptoOperation(new CryptoInputParcel());
+ mOperationHelper.cryptoOperation();
}
protected void cryptoOperation(CryptoInputParcel cryptoInput) {
- cryptoOperation(cryptoInput, true);
+ mOperationHelper.cryptoOperation(cryptoInput);
}
protected void cryptoOperation(CryptoInputParcel cryptoInput, boolean showProgress) {
mOperationHelper.cryptoOperation(cryptoInput, showProgress);
}
+ @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;
}
+ 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
public void onCryptoOperationError(S result) {
- onCryptoOperationResult(result);
result.createNotify(getActivity()).show();
}
@@ -77,19 +109,4 @@ public abstract class CryptoOperationFragment<T extends Parcelable, S extends Op
public void onCryptoOperationCancelled() {
}
- @Override
- public void onCryptoOperationSuccess(S result) {
- onCryptoOperationResult(result);
- }
-
- /**
- *
- * To be overriden by subclasses, if desired. Provides a way to access the method by the
- * same name in CryptoOperationHelper, if super.onCryptoOperationSuccess and
- * super.onCryptoOperationError are called at the start of the respective functions in the
- * subclass overriding them
- * @param result
- */
- protected void onCryptoOperationResult(S result) {
- }
}
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 240dd0972..8d141ea5d 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
@@ -28,8 +28,8 @@ import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
-
import android.support.v4.app.FragmentManager;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
@@ -39,6 +39,7 @@ import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
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.OrbotRequiredDialogActivity;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@@ -52,16 +53,21 @@ import org.sufficientlysecure.keychain.util.Log;
*/
public class CryptoOperationHelper<T extends Parcelable, S extends OperationResult> {
- public interface Callback <T extends Parcelable, S extends OperationResult> {
+ public interface Callback<T extends Parcelable, S extends OperationResult> {
T createOperationInput();
+
void onCryptoOperationSuccess(S result);
+
void onCryptoOperationCancelled();
+
void onCryptoOperationError(S result);
+
boolean onCryptoSetProgress(String msg, int progress, int max);
}
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
public static final int REQUEST_CODE_NFC = 0x00008002;
+ public static final int REQUEST_CODE_ENABLE_ORBOT = 0x00008004;
// keeps track of request code used to start an activity from this CryptoOperationHelper.
// this is necessary when multiple CryptoOperationHelpers are used in the same fragment/activity
@@ -78,8 +84,6 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
/**
* If OperationHelper is being integrated into an activity
- *
- * @param activity
*/
public CryptoOperationHelper(FragmentActivity activity, Callback<T, S> callback, int progressMessageString) {
mActivity = activity;
@@ -90,8 +94,6 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
/**
* if OperationHelper is being integrated into a fragment
- *
- * @param fragment
*/
public CryptoOperationHelper(Fragment fragment, Callback<T, S> callback, int progressMessageString) {
mFragment = fragment;
@@ -102,8 +104,6 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
/**
* if OperationHelper is being integrated into a fragment with default message for the progress dialog
- *
- * @param fragment
*/
public CryptoOperationHelper(Fragment fragment, Callback<T, S> callback) {
mFragment = fragment;
@@ -116,11 +116,14 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
mProgressMessageResource = id;
}
- private void initiateInputActivity(RequiredInputParcel requiredInput) {
+ private void initiateInputActivity(RequiredInputParcel requiredInput,
+ CryptoInputParcel cryptoInputParcel) {
Activity activity = mUseFragment ? mFragment.getActivity() : mActivity;
switch (requiredInput.mType) {
+ // TODO: Verify that all started activities add to cryptoInputParcel if necessary (like OrbotRequiredDialogActivity)
+ // don't forget to set mRequestedCode!
case NFC_MOVE_KEY_TO_CARD:
case NFC_DECRYPT:
case NFC_SIGN: {
@@ -130,7 +133,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
if (mUseFragment) {
mFragment.startActivityForResult(intent, mRequestedCode);
} else {
- mActivity.startActivityForResult(intent, mRequestedCode);
+ activity.startActivityForResult(intent, mRequestedCode);
}
return;
}
@@ -143,22 +146,32 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
if (mUseFragment) {
mFragment.startActivityForResult(intent, mRequestedCode);
} else {
- mActivity.startActivityForResult(intent, mRequestedCode);
+ activity.startActivityForResult(intent, mRequestedCode);
}
return;
}
- }
- throw new RuntimeException("Unhandled pending result!");
+ case ENABLE_ORBOT: {
+ Intent intent = new Intent(activity, OrbotRequiredDialogActivity.class);
+ intent.putExtra(OrbotRequiredDialogActivity.EXTRA_CRYPTO_INPUT, cryptoInputParcel);
+ mRequestedCode = REQUEST_CODE_ENABLE_ORBOT;
+ if (mUseFragment) {
+ mFragment.startActivityForResult(intent, mRequestedCode);
+ } else {
+ activity.startActivityForResult(intent, mRequestedCode);
+ }
+ return;
+ }
+
+ default: {
+ throw new RuntimeException("Unhandled pending result!");
+ }
+ }
}
/**
- * Attempts the result of an activity started by this helper. Returns true if requestCode is recognized,
- * false otherwise.
- *
- * @param requestCode
- * @param resultCode
- * @param data
+ * Attempts the result of an activity started by this helper. Returns true if requestCode is
+ * recognized, false otherwise.
* @return true if requestCode was recognized, false otherwise
*/
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
@@ -196,6 +209,16 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
break;
}
+ case REQUEST_CODE_ENABLE_ORBOT: {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ CryptoInputParcel cryptoInput =
+ data.getParcelableExtra(
+ OrbotRequiredDialogActivity.RESULT_CRYPTO_INPUT);
+ cryptoOperation(cryptoInput);
+ return true;
+ }
+ }
+
default: {
return false;
}
@@ -225,7 +248,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
}
- public void cryptoOperation(CryptoInputParcel cryptoInput, boolean showProgress) {
+ public void cryptoOperation(final CryptoInputParcel cryptoInput, boolean showProgress) {
FragmentActivity activity = mUseFragment ? mFragment.getActivity() : mActivity;
@@ -257,14 +280,14 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
final OperationResult result =
returnData.getParcelable(OperationResult.EXTRA_RESULT);
- onHandleResult(result);
+ onHandleResult(result, cryptoInput);
}
}
@Override
protected void onSetProgress(String msg, int progress, int max) {
// allow handling of progress in fragment, or delegate upwards
- if ( ! mCallback.onCryptoSetProgress(msg, progress, max)) {
+ if (!mCallback.onCryptoSetProgress(msg, progress, max)) {
super.onSetProgress(msg, progress, max);
}
}
@@ -291,15 +314,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
cryptoOperation(new CryptoInputParcel());
}
- protected void onCryptoOperationResult(S result) {
- if (result.success()) {
- mCallback.onCryptoOperationSuccess(result);
- } else {
- mCallback.onCryptoOperationError(result);
- }
- }
-
- public void onHandleResult(OperationResult result) {
+ public void onHandleResult(OperationResult result, CryptoInputParcel oldCryptoInput) {
Log.d(Constants.TAG, "Handling result in OperationHelper success: " + result.success());
if (result instanceof InputPendingResult) {
@@ -307,7 +322,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
if (pendingResult.isPending()) {
RequiredInputParcel requiredInput = pendingResult.getRequiredInputParcel();
- initiateInputActivity(requiredInput);
+ initiateInputActivity(requiredInput, oldCryptoInput);
return;
}
}
@@ -315,8 +330,13 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
dismissProgress();
try {
- // noinspection unchecked, because type erasure :(
- onCryptoOperationResult((S) result);
+ if (result.success()) {
+ // noinspection unchecked, because type erasure :(
+ mCallback.onCryptoOperationSuccess((S) result);
+ } else {
+ // noinspection unchecked, because type erasure :(
+ mCallback.onCryptoOperationError((S) result);
+ }
} catch (ClassCastException e) {
throw new AssertionError("bad return class ("
+ result.getClass().getSimpleName() + "), this is a programming error!");
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java
index 321242b2f..b8d93dc00 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEditKeyserverDialogFragment.java
@@ -48,10 +48,17 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.TlsHelper;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
+
+import java.net.Proxy;
public class AddEditKeyserverDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "arg_messenger";
@@ -205,9 +212,21 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
@Override
public void onClick(View v) {
// behaviour same for edit and add
- String keyserverUrl = mKeyserverEditText.getText().toString();
+ final String keyserverUrl = mKeyserverEditText.getText().toString();
if (mVerifyKeyserverCheckBox.isChecked()) {
- verifyConnection(keyserverUrl);
+ final Preferences.ProxyPrefs proxyPrefs = Preferences.getPreferences(getActivity())
+ .getProxyPrefs();
+ Runnable ignoreTor = new Runnable() {
+ @Override
+ public void run() {
+ verifyConnection(keyserverUrl, null);
+ }
+ };
+
+ if (OrbotHelper.putOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, proxyPrefs,
+ getActivity())) {
+ verifyConnection(keyserverUrl, proxyPrefs.parcelableProxy.getProxy());
+ }
} else {
dismiss();
// return unverified keyserver back to activity
@@ -249,7 +268,7 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
sendMessageToHandler(MESSAGE_VERIFICATION_FAILED, data);
}
- public void verifyConnection(String keyserver) {
+ public void verifyConnection(String keyserver, final Proxy proxy) {
new AsyncTask<String, Void, FailureReason>() {
ProgressDialog mProgressDialog;
@@ -283,10 +302,11 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
}
URI newKeyserver = new URI(scheme, schemeSpecificPart, fragment);
- Log.d(Constants.TAG, "Converted URL" + newKeyserver);
+ Log.d("Converted URL", newKeyserver.toString());
- // just see if we can get a connection, then immediately close
- TlsHelper.openConnection(newKeyserver.toURL()).getInputStream().close();
+ OkHttpClient client = HkpKeyserver.getClient(newKeyserver.toURL(), proxy);
+ TlsHelper.pinCertificateIfNecessary(client, newKeyserver.toURL());
+ client.newCall(new Request.Builder().url(newKeyserver.toURL()).build()).execute();
} catch (TlsHelper.TlsHelperException e) {
reason = FailureReason.CONNECTION_FAILED;
} catch (MalformedURLException | URISyntaxException e) {
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
new file mode 100644
index 000000000..dd7d2256a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.dialog;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Message;
+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;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
+
+/**
+ * displays a dialog asking the user to enable Tor
+ */
+public class OrbotStartDialogFragment extends DialogFragment {
+ private static final String ARG_MESSENGER = "messenger";
+ private static final String ARG_TITLE = "title";
+ private static final String ARG_MESSAGE = "message";
+ private static final String ARG_MIDDLE_BUTTON = "middleButton";
+
+ public static final int MESSAGE_MIDDLE_BUTTON = 1;
+ public static final int MESSAGE_DIALOG_DISMISSED = 2; // for either cancel or enable pressed
+
+ public static OrbotStartDialogFragment newInstance(Messenger messenger, int title, int message, int middleButton) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_MESSENGER, messenger);
+ args.putInt(ARG_TITLE, title);
+ args.putInt(ARG_MESSAGE, message);
+ args.putInt(ARG_MIDDLE_BUTTON, middleButton);
+
+ OrbotStartDialogFragment fragment = new OrbotStartDialogFragment();
+ fragment.setArguments(args);
+
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+
+ final Messenger messenger = getArguments().getParcelable(ARG_MESSENGER);
+ int title = getArguments().getInt(ARG_TITLE);
+ final int message = getArguments().getInt(ARG_MESSAGE);
+ int middleButton = getArguments().getInt(ARG_MIDDLE_BUTTON);
+ final Activity activity = 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() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Message msg = Message.obtain();
+ msg.what = MESSAGE_DIALOG_DISMISSED;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+
+ }
+ });
+
+ builder.setPositiveButton(R.string.orbot_start_dialog_start, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ getActivity().startActivityForResult(OrbotHelper.getOrbotStartIntent(), 1);
+
+ Message msg = Message.obtain();
+ msg.what = MESSAGE_DIALOG_DISMISSED;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+ });
+
+ builder.setNeutralButton(middleButton, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Message msg = new Message();
+ msg.what = MESSAGE_MIDDLE_BUTTON;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+ });
+
+ return builder.show();
+ }
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java
new file mode 100644
index 000000000..3f8bce28b
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.dialog;
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.os.Messenger;
+import android.app.DialogFragment;
+
+import org.sufficientlysecure.keychain.ui.util.InstallDialogFragmentHelper;
+
+public class PreferenceInstallDialogFragment extends DialogFragment {
+
+ public static final int MESSAGE_MIDDLE_CLICKED = 1;
+ public static final int MESSAGE_DIALOG_DISMISSED = 2;
+
+ /**
+ * Creates a dialog which prompts the user to install an application. Consists of two default buttons ("Install"
+ * and "Cancel") and an optional third button. Callbacks are provided only for the middle button, if set.
+ *
+ * @param messenger required only for callback from middle button if it has been set
+ * @param title
+ * @param message content of dialog
+ * @param packageToInstall package name of application to install
+ * @param middleButton if not null, adds a third button to the app with a call back
+ * @return The dialog to display
+ */
+ public static PreferenceInstallDialogFragment newInstance(Messenger messenger, int title, int message,
+ String packageToInstall, int middleButton, boolean
+ useMiddleButton) {
+ PreferenceInstallDialogFragment frag = new PreferenceInstallDialogFragment();
+ Bundle args = new Bundle();
+
+ InstallDialogFragmentHelper.wrapIntoArgs(messenger, title, message, packageToInstall, middleButton,
+ useMiddleButton, args);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * To create a DialogFragment with only two buttons
+ *
+ * @param title
+ * @param message
+ * @param packageToInstall
+ * @return
+ */
+ public static PreferenceInstallDialogFragment newInstance(int title, int message,
+ String packageToInstall) {
+ return newInstance(null, title, message, packageToInstall, -1, false);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return InstallDialogFragmentHelper.getInstallDialogFromArgs(getArguments(), getActivity(),
+ MESSAGE_MIDDLE_CLICKED, MESSAGE_DIALOG_DISMISSED);
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SupportInstallDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SupportInstallDialogFragment.java
new file mode 100644
index 000000000..b2b71b364
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SupportInstallDialogFragment.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.dialog;
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.os.Messenger;
+import android.support.v4.app.DialogFragment;
+
+import org.sufficientlysecure.keychain.ui.util.InstallDialogFragmentHelper;
+
+public class SupportInstallDialogFragment extends DialogFragment {
+
+ public static final int MESSAGE_MIDDLE_CLICKED = 1;
+ public static final int MESSAGE_DIALOG_DISMISSED = 2;
+
+ /**
+ * Creates a dialog which prompts the user to install an application. Consists of two default buttons ("Install"
+ * and "Cancel") and an optional third button. Callbacks are provided only for the middle button, if set.
+ *
+ * @param messenger required only for callback from middle button if it has been set
+ * @param title
+ * @param message content of dialog
+ * @param packageToInstall package name of application to install
+ * @param middleButton if not null, adds a third button to the app with a call back
+ * @return The dialog to display
+ */
+ public static SupportInstallDialogFragment newInstance(Messenger messenger, int title, int message,
+ String packageToInstall, int middleButton, boolean
+ useMiddleButton) {
+ SupportInstallDialogFragment frag = new SupportInstallDialogFragment();
+ Bundle args = new Bundle();
+
+ InstallDialogFragmentHelper.wrapIntoArgs(messenger, title, message, packageToInstall, middleButton,
+ useMiddleButton, args);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * To create a DialogFragment with only two buttons
+ *
+ * @param title
+ * @param message
+ * @param packageToInstall
+ * @return
+ */
+ public static SupportInstallDialogFragment newInstance(int title, int message,
+ String packageToInstall) {
+ return newInstance(null, title, message, packageToInstall, -1, false);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+
+ return InstallDialogFragmentHelper.getInstallDialogFromArgs(getArguments(), getActivity(),
+ MESSAGE_MIDDLE_CLICKED, MESSAGE_DIALOG_DISMISSED);
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/InstallDialogFragmentHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/InstallDialogFragmentHelper.java
new file mode 100644
index 000000000..f21d69c48
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/InstallDialogFragmentHelper.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.view.ContextThemeWrapper;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class InstallDialogFragmentHelper {
+ private static final String ARG_MESSENGER = "messenger";
+ private static final String ARG_TITLE = "title";
+ private static final String ARG_MESSAGE = "message";
+ private static final String ARG_MIDDLE_BUTTON = "middleButton";
+ private static final String ARG_INSTALL_PATH = "installPath";
+ private static final String ARG_USE_MIDDLE_BUTTON = "useMiddleButton";
+
+ private static final String PLAY_STORE_PATH = "market://search?q=pname:";
+
+ public static void wrapIntoArgs(Messenger messenger, int title, int message, String packageToInstall,
+ int middleButton, boolean useMiddleButton, Bundle args) {
+ args.putParcelable(ARG_MESSENGER, messenger);
+
+ args.putInt(ARG_TITLE, title);
+ args.putInt(ARG_MESSAGE, message);
+ args.putInt(ARG_MIDDLE_BUTTON, middleButton);
+ args.putString(ARG_INSTALL_PATH, PLAY_STORE_PATH + packageToInstall);
+ args.putBoolean(ARG_USE_MIDDLE_BUTTON, useMiddleButton);
+ }
+
+ public static AlertDialog getInstallDialogFromArgs(Bundle args, final Activity activity,
+ final int messengerMiddleButtonClicked,
+ final int messengerDialogDimissed) {
+ final Messenger messenger = args.getParcelable(ARG_MESSENGER);
+
+ final int title = args.getInt(ARG_TITLE);
+ final int message = args.getInt(ARG_MESSAGE);
+ final int middleButton = args.getInt(ARG_MIDDLE_BUTTON);
+ final String installPath = args.getString(ARG_INSTALL_PATH);
+ final boolean useMiddleButton = args.getBoolean(ARG_USE_MIDDLE_BUTTON);
+
+ // 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_install_dialog_cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Message msg = Message.obtain();
+ msg.what = messengerDialogDimissed;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+ });
+
+ builder.setPositiveButton(R.string.orbot_install_dialog_install,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Uri uri = Uri.parse(installPath);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ activity.startActivity(intent);
+
+ Message msg = Message.obtain();
+ msg.what = messengerDialogDimissed;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+ }
+ );
+
+ if (useMiddleButton) {
+ builder.setNeutralButton(middleButton,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Message msg = Message.obtain();
+ msg.what = messengerMiddleButtonClicked;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+ }
+ );
+ }
+
+ return builder.show();
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java
index 0ec145657..30bdfb92a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java
@@ -31,7 +31,9 @@ import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Log;
/**
* Created by Matt Allen