diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-05-05 10:10:47 +0200 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-05-05 10:10:47 +0200 |
commit | 6d10ca678a541dddb26f43c9d415d14f6f5eceaf (patch) | |
tree | ee097be93497a90139f982bbf9851eeb2115dafd /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui | |
parent | e48460bb7df8f2d40fe187f8c267fbba3fb43c75 (diff) | |
parent | 90b4db07925ec4741fedfa75eed4ed6acc533696 (diff) | |
download | open-keychain-6d10ca678a541dddb26f43c9d415d14f6f5eceaf.tar.gz open-keychain-6d10ca678a541dddb26f43c9d415d14f6f5eceaf.tar.bz2 open-keychain-6d10ca678a541dddb26f43c9d415d14f6f5eceaf.zip |
Merge pull request #603 from timbray/master
Adds first level of keybase support
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
10 files changed, 318 insertions, 14 deletions
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 0fccd668f..650e51069 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -62,6 +62,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O + "IMPORT_KEY_FROM_KEYSERVER"; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN"; + public static final String ACTION_IMPORT_KEY_FROM_KEYBASE = Constants.INTENT_PREFIX + + "IMPORT_KEY_FROM_KEYBASE"; // Actions for internal use only: public static final String ACTION_IMPORT_KEY_FROM_FILE = Constants.INTENT_PREFIX @@ -92,13 +94,15 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O ImportKeysFileFragment.class, ImportKeysQrCodeFragment.class, ImportKeysClipboardFragment.class, - ImportKeysNFCFragment.class + ImportKeysNFCFragment.class, + ImportKeysKeybaseFragment.class }; private static final int NAV_SERVER = 0; private static final int NAV_FILE = 1; private static final int NAV_QR_CODE = 2; private static final int NAV_CLIPBOARD = 3; private static final int NAV_NFC = 4; + private static final int NAV_KEYBASE = 5; private int mCurrentNavPosition = -1; @@ -238,6 +242,12 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O // no immediate actions! startListFragment(savedInstanceState, null, null, null); + } else if (ACTION_IMPORT_KEY_FROM_KEYBASE.equals(action)) { + // NOTE: this only displays the appropriate fragment, no actions are taken + loadNavFragment(NAV_KEYBASE, null); + + // no immediate actions! + startListFragment(savedInstanceState, null, null, null); } else { startListFragment(savedInstanceState, null, null, null); } @@ -340,8 +350,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O startListFragment(savedInstanceState, null, null, query); } - public void loadCallback(byte[] importData, Uri dataUri, String serverQuery, String keyServer) { - mListFragment.loadNew(importData, dataUri, serverQuery, keyServer); + public void loadCallback(byte[] importData, Uri dataUri, String serverQuery, String keyServer, String keybaseQuery) { + mListFragment.loadNew(importData, dataUri, serverQuery, keyServer, keybaseQuery); } /** @@ -449,6 +459,31 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O // start service with intent startService(intent); + } else if (mListFragment.getKeybaseQuery() != null) { + // Send all information needed to service to query keys in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYBASE_KEYS); + + // fill values for this action + Bundle data = new Bundle(); + + // get selected key entries + ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedData(); + data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } else { AppMsg.makeText(this, R.string.error_nothing_import, AppMsg.STYLE_ALERT).show(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java index 412fbddd8..f331358fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java @@ -71,7 +71,7 @@ public class ImportKeysClipboardFragment extends Fragment { return; } } - mImportActivity.loadCallback(sendText.getBytes(), null, null, null); + mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null); } }); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java index dc5333a8f..51f961aab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java @@ -85,7 +85,7 @@ public class ImportKeysFileFragment extends Fragment { if (resultCode == Activity.RESULT_OK && data != null) { // load data - mImportActivity.loadCallback(null, data.getData(), null, null); + mImportActivity.loadCallback(null, data.getData(), null, null, null); } break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java new file mode 100644 index 000000000..a996079c9 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 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; + +import android.content.Context; +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.beardedhen.androidbootstrap.BootstrapButton; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +/** + * Import public keys from the Keybase.io directory. First cut: just raw search. + * TODO: make a pick list of the people you’re following on keybase + */ +public class ImportKeysKeybaseFragment extends Fragment { + + private ImportKeysActivity mImportActivity; + private BootstrapButton mSearchButton; + private EditText mQueryEditText; + + public static final String ARG_QUERY = "query"; + + /** + * Creates new instance of this fragment + */ + public static ImportKeysKeybaseFragment newInstance() { + ImportKeysKeybaseFragment frag = new ImportKeysKeybaseFragment(); + + Bundle args = new Bundle(); + frag.setArguments(args); + + return frag; + } + + /** + * Inflate the layout for this fragment + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.import_keys_keybase_fragment, container, false); + + mQueryEditText = (EditText) view.findViewById(R.id.import_keybase_query); + + mSearchButton = (BootstrapButton) view.findViewById(R.id.import_keybase_search); + mSearchButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String query = mQueryEditText.getText().toString(); + search(query); + + // close keyboard after pressing search + InputMethodManager imm = + (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mQueryEditText.getWindowToken(), 0); + } + }); + + mQueryEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + String query = mQueryEditText.getText().toString(); + search(query); + + // Don't return true to let the keyboard close itself after pressing search + return false; + } + return false; + } + }); + + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mImportActivity = (ImportKeysActivity) getActivity(); + + // set displayed values + if (getArguments() != null) { + if (getArguments().containsKey(ARG_QUERY)) { + String query = getArguments().getString(ARG_QUERY); + mQueryEditText.setText(query, TextView.BufferType.EDITABLE); + } + } + } + + private void search(String query) { + mImportActivity.loadCallback(null, null, null, null, query); + } +} 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 3a6c384e8..c1aa8a1f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; +import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListKeybaseLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader; import org.sufficientlysecure.keychain.util.InputData; @@ -60,9 +61,11 @@ public class ImportKeysListFragment extends ListFragment implements private Uri mDataUri; private String mServerQuery; private String mKeyServer; + private String mKeybaseQuery; private static final int LOADER_ID_BYTES = 0; private static final int LOADER_ID_SERVER_QUERY = 1; + private static final int LOADER_ID_KEYBASE = 2; public byte[] getKeyBytes() { return mKeyBytes; @@ -76,6 +79,10 @@ public class ImportKeysListFragment extends ListFragment implements return mServerQuery; } + public String getKeybaseQuery() { + return mKeybaseQuery; + } + public String getKeyServer() { return mKeyServer; } @@ -148,6 +155,16 @@ public class ImportKeysListFragment extends ListFragment implements // give arguments to onCreateLoader() getLoaderManager().initLoader(LOADER_ID_SERVER_QUERY, null, this); } + + if (mKeybaseQuery != null) { + // Start out with a progress indicator. + setListShown(false); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + // give arguments to onCreateLoader() + getLoaderManager().initLoader(LOADER_ID_KEYBASE, null, this); + } } @Override @@ -157,16 +174,18 @@ public class ImportKeysListFragment extends ListFragment implements // Select checkbox! // Update underlying data and notify adapter of change. The adapter will // update the view automatically. + ImportKeysListEntry entry = mAdapter.getItem(position); entry.setSelected(!entry.isSelected()); mAdapter.notifyDataSetChanged(); } - public void loadNew(byte[] keyBytes, Uri dataUri, String serverQuery, String keyServer) { + public void loadNew(byte[] keyBytes, Uri dataUri, String serverQuery, String keyServer, String keybaseQuery) { mKeyBytes = keyBytes; mDataUri = dataUri; mServerQuery = serverQuery; mKeyServer = keyServer; + mKeybaseQuery = keybaseQuery; if (mKeyBytes != null || mDataUri != null) { // Start out with a progress indicator. @@ -181,6 +200,13 @@ public class ImportKeysListFragment extends ListFragment implements getLoaderManager().restartLoader(LOADER_ID_SERVER_QUERY, null, this); } + + if (mKeybaseQuery != null) { + // Start out with a progress indicator. + setListShown(false); + + getLoaderManager().restartLoader(LOADER_ID_KEYBASE, null, this); + } } @Override @@ -194,6 +220,9 @@ public class ImportKeysListFragment extends ListFragment implements case LOADER_ID_SERVER_QUERY: { return new ImportKeysListServerLoader(getActivity(), mServerQuery, mKeyServer); } + case LOADER_ID_KEYBASE: { + return new ImportKeysListKeybaseLoader(getActivity(), mKeybaseQuery); + } default: return null; @@ -248,7 +277,7 @@ public class ImportKeysListFragment extends ListFragment implements if (error == null) { AppMsg.makeText( getActivity(), getResources().getQuantityString(R.plurals.keys_found, - mAdapter.getCount(), mAdapter.getCount()), + mAdapter.getCount(), mAdapter.getCount()), AppMsg.STYLE_INFO ).show(); } else if (error instanceof KeyServer.InsufficientQuery) { @@ -263,6 +292,19 @@ public class ImportKeysListFragment extends ListFragment implements } break; + case LOADER_ID_KEYBASE: + + if (error == null) { + AppMsg.makeText( + getActivity(), getResources().getQuantityString(R.plurals.keys_found, + mAdapter.getCount(), mAdapter.getCount()), + AppMsg.STYLE_INFO + ).show(); + } else if (error instanceof KeyServer.QueryException) { + AppMsg.makeText(getActivity(), R.string.error_keyserver_query, + AppMsg.STYLE_ALERT).show(); + } + default: break; } @@ -279,6 +321,10 @@ public class ImportKeysListFragment extends ListFragment implements // Clear the data in the adapter. mAdapter.clear(); break; + case LOADER_ID_KEYBASE: + // Clear the data in the adapter. + mAdapter.clear(); + break; default: break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index 65d463456..22b56e1ab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -117,7 +117,7 @@ public class ImportKeysQrCodeFragment extends Fragment { // is this a full key encoded as qr code? if (scannedContent.startsWith("-----BEGIN PGP")) { - mImportActivity.loadCallback(scannedContent.getBytes(), null, null, null); + mImportActivity.loadCallback(scannedContent.getBytes(), null, null, null, null); return; } @@ -197,7 +197,7 @@ public class ImportKeysQrCodeFragment extends Fragment { for (String in : mScannedContent) { result += in; } - mImportActivity.loadCallback(result.getBytes(), null, null, null); + mImportActivity.loadCallback(result.getBytes(), null, null, null, null); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java index 82fe2fc4c..9e3d88ff5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java @@ -151,7 +151,7 @@ public class ImportKeysServerFragment extends Fragment { } private void search(String query, String keyServer) { - mImportActivity.loadCallback(null, null, query, keyServer); + mImportActivity.loadCallback(null, null, query, keyServer, null); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java index b06852af4..1610bfeab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java @@ -203,7 +203,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { * Constructor for later querying from keyserver */ public ImportKeysListEntry() { - // keys from keyserver are always public keys + // keys from keyserver are always public keys; from keybase too secretKey = false; // do not select by default mSelected = false; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListKeybaseLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListKeybaseLoader.java new file mode 100644 index 000000000..e66032482 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListKeybaseLoader.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 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.adapter; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.KeyServer; +import org.sufficientlysecure.keychain.util.KeybaseKeyServer; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.ArrayList; + +public class ImportKeysListKeybaseLoader + extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { + Context mContext; + + String mKeybaseQuery; + + private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<ImportKeysListEntry>(); + private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper; + + public ImportKeysListKeybaseLoader(Context context, String keybaseQuery) { + super(context); + mContext = context; + mKeybaseQuery = keybaseQuery; + } + + @Override + public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() { + + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null); + + if (mKeybaseQuery == null) { + Log.e(Constants.TAG, "mKeybaseQery is null!"); + return mEntryListWrapper; + } + + queryServer(mKeybaseQuery); + + return mEntryListWrapper; + } + + @Override + protected void onReset() { + super.onReset(); + + // Ensure the loader is stopped + onStopLoading(); + } + + @Override + protected void onStartLoading() { + forceLoad(); + } + + @Override + protected void onStopLoading() { + cancelLoad(); + } + + @Override + public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) { + super.deliverResult(data); + } + + /** + * Query keybase + */ + private void queryServer(String query) { + + KeybaseKeyServer server = new KeybaseKeyServer(); + try { + ArrayList<ImportKeysListEntry> searchResult = server.search(query); + + mEntryList.clear(); + + mEntryList.addAll(searchResult); + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null); + } catch (KeyServer.InsufficientQuery e) { + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); + } catch (KeyServer.QueryException e) { + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); + } catch (KeyServer.TooManyResponses e) { + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); + } + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java index 838aeefee..65810064c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java @@ -116,13 +116,10 @@ public class ImportKeysListServerLoader } mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null); } catch (KeyServer.InsufficientQuery e) { - Log.e(Constants.TAG, "InsufficientQuery", e); mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); } catch (KeyServer.QueryException e) { - Log.e(Constants.TAG, "QueryException", e); mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); } catch (KeyServer.TooManyResponses e) { - Log.e(Constants.TAG, "TooManyResponses", e); mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, e); } } |