Merge branch 'master' of github.com:open-keychain/open-keychain
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -210,7 +210,7 @@ public class ViewKeyYubiKeyFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCryptoOperationResult(PromoteKeyResult result) {
|
||||
public void onCryptoOperationSuccess(PromoteKeyResult result) {
|
||||
result.createNotify(getActivity()).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user