From 5af4f6b63f366d0ece4fcab5c513036e163b1432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 5 Apr 2014 22:55:32 +0200 Subject: [PATCH] Fix nfc, make edit activity like a modal dialog, move all menu actions into view activity --- .../keychain/provider/ProviderHelper.java | 17 ++- .../keychain/ui/EditKeyActivity.java | 101 +++++------------- .../keychain/ui/ViewKeyActivity.java | 30 ++++-- .../keychain/ui/ViewKeyActivityJB.java | 20 ++-- .../keychain/ui/ViewKeyMainFragment.java | 12 --- .../res/layout/view_key_main_fragment.xml | 3 +- .../src/main/res/menu/key_edit.xml | 24 ----- 7 files changed, 66 insertions(+), 141 deletions(-) delete mode 100644 OpenPGP-Keychain/src/main/res/menu/key_edit.xml diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 581ddb378..3d1d663c7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -23,10 +23,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.Cursor; -import android.database.CursorWindow; -import android.database.CursorWrapper; import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteCursor; import android.net.Uri; import android.os.RemoteException; @@ -42,8 +39,8 @@ import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.remote.AccountSettings; @@ -72,6 +69,7 @@ public class ProviderHelper { public static Object getGenericData(Context context, Uri uri, String column, int type) { return getGenericData(context, uri, new String[] { column }, new int[] { type }).get(column); } + public static HashMap getGenericData(Context context, Uri uri, String[] proj, int[] types) { Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null); @@ -100,11 +98,13 @@ public class ProviderHelper { public static Object getUnifiedData(Context context, long masterKeyId, String column, int type) { return getUnifiedData(context, masterKeyId, new String[] { column }, new int[] { type }).get(column); } + public static HashMap getUnifiedData(Context context, long masterKeyId, String[] proj, int[] types) { return getGenericData(context, KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), proj, types); } - /** Find the master key id related to a given query. The id will either be extracted from the + /** + * Find the master key id related to a given query. The id will either be extracted from the * query, which should work for all specific /key_rings/ queries, or will be queried if it can't. */ public static long getMasterKeyId(Context context, Uri queryUri) { @@ -333,12 +333,6 @@ public class ProviderHelper { return ContentProviderOperation.newInsert(uri).withValues(values).build(); } - public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) { - Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); - // see if we can get our master key id back from the uri - return getMasterKeyId(context, queryUri) == masterKeyId; - } - public static ArrayList getKeyRingsAsArmoredString(Context context, long[] masterKeyIds) { ArrayList output = new ArrayList(); @@ -398,6 +392,7 @@ public class ProviderHelper { return null; } } + private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, long[] masterKeyIds) { Cursor cursor = null; if (masterKeyIds != null && masterKeyIds.length > 0) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 60bababd1..6e6a7e47a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -31,8 +31,6 @@ import android.os.Messenger; import android.support.v4.app.ActivityCompat; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -47,22 +45,20 @@ import com.devspark.appmsg.AppMsg; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.helper.ExportHelper; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.widget.Editor; @@ -142,9 +138,24 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener mExportHelper = new ExportHelper(this); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setIcon(android.R.color.transparent); - getSupportActionBar().setHomeButtonEnabled(true); + // Inflate a "Done"/"Cancel" custom action bar view + ActionBarHelper.setTwoButtonView(getSupportActionBar(), + R.string.btn_save, R.drawable.ic_action_save, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Save + saveClicked(); + } + }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Cancel + cancelClicked(); + } + } + ); mUserIds = new Vector(); mKeys = new Vector(); @@ -281,62 +292,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener } } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.key_edit, menu); - //totally get rid of some actions for new keys - if (mDataUri == null) { - MenuItem mButton = menu.findItem(R.id.menu_key_edit_export_file); - mButton.setVisible(false); - mButton = menu.findItem(R.id.menu_key_edit_delete); - mButton.setVisible(false); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - cancelClicked(); - // TODO: why isn't this triggered on my tablet - one of many ui problems - // I've had with this device. A code compatibility issue or a Samsung fail? - return true; - case R.id.menu_key_edit_cancel: - cancelClicked(); - return true; - case R.id.menu_key_edit_export_file: - if (needsSaving()) { - Toast.makeText(this, R.string.error_save_first, Toast.LENGTH_LONG).show(); - } else { - long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri); - mExportHelper.showExportKeysDialog( - new long[] { masterKeyId }, Constants.Path.APP_DIR_FILE_SEC, true); - return true; - } - return true; - case R.id.menu_key_edit_delete: - Uri convertUri = KeyRingData.buildSecretKeyRingUri(mDataUri); - // Message is received after key is deleted - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) { - setResult(RESULT_CANCELED); - finish(); - } - }}; - mExportHelper.deleteKey(convertUri, returnHandler); - return true; - - case R.id.menu_key_edit_save: - saveClicked(); - return true; - } - return super.onOptionsItemSelected(item); - } - @SuppressWarnings("unchecked") private void finallyEdit(final long masterKeyId) { if (masterKeyId != 0) { @@ -525,16 +480,16 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener } if (passphrase == null) { PassphraseDialogFragment.show(this, masterKeyId, - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase( - EditKeyActivity.this, masterKeyId); - checkEmptyIDsWanted(); + new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase( + EditKeyActivity.this, masterKeyId); + checkEmptyIDsWanted(); + } } - } - }); + }); } else { mCurrentPassphrase = passphrase; checkEmptyIDsWanted(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 7b9ba4b2d..7f4e97937 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -31,6 +31,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.widget.Toast; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; @@ -44,6 +45,7 @@ import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment; import java.util.ArrayList; +import java.util.HashMap; public class ViewKeyActivity extends ActionBarActivity { @@ -119,12 +121,7 @@ public class ViewKeyActivity extends ActionBarActivity { uploadToKeyserver(mDataUri); return true; case R.id.menu_key_view_export_file: - long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri); - mExportHelper.showExportKeysDialog( - new long[] { masterKeyId } , Constants.Path.APP_DIR_FILE_PUB, - // TODO this doesn't work? - ((ViewKeyMainFragment) mTabsAdapter.getItem(0)).isSecretAvailable() - ); + exportToFile(mDataUri); return true; case R.id.menu_key_view_share_default_fingerprint: shareKey(mDataUri, true); @@ -152,6 +149,21 @@ public class ViewKeyActivity extends ActionBarActivity { return super.onOptionsItemSelected(item); } + private void exportToFile(Uri dataUri) { + Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri); + + HashMap data = ProviderHelper.getGenericData(this, + baseUri, + new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET}, + new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER}); + + mExportHelper.showExportKeysDialog( + new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)}, + Constants.Path.APP_DIR_FILE_PUB, + ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) == 1) + ); + } + private void uploadToKeyserver(Uri dataUri) { Intent uploadIntent = new Intent(this, UploadKeyActivity.class); uploadIntent.setData(dataUri); @@ -177,7 +189,7 @@ public class ViewKeyActivity extends ActionBarActivity { byte[] data = (byte[]) ProviderHelper.getGenericData( this, KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - if(data != null) { + if (data != null) { String fingerprint = PgpKeyHelper.convertFingerprintToHex(data); content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { @@ -189,7 +201,7 @@ public class ViewKeyActivity extends ActionBarActivity { // get public keyring as ascii armored string long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - this, new long[]{ masterKeyId }); + this, new long[]{masterKeyId}); content = keyringArmored.get(0); @@ -220,7 +232,7 @@ public class ViewKeyActivity extends ActionBarActivity { // get public keyring as ascii armored string long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - this, new long[]{ masterKeyId }); + this, new long[]{masterKeyId}); ClipboardReflection.copyToClipboard(this, keyringArmored.get(0)); Toast.makeText(getApplicationContext(), R.string.key_copied_to_clipboard, Toast.LENGTH_LONG) diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java index 6ce7d9aa8..6dc0413bb 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java @@ -1,6 +1,5 @@ /* * Copyright (C) 2013-2014 Dominik Schürmann - * Copyright (C) 2013 Bahtiar 'kalkin' Gadimov * * 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 @@ -19,7 +18,6 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; -import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; @@ -31,6 +29,9 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.Toast; + +import com.devspark.appmsg.AppMsg; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -42,7 +43,6 @@ import java.io.IOException; public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback { - // NFC private NfcAdapter mNfcAdapter; private byte[] mSharedKeyringBytes; private static final int NFC_SENT = 1; @@ -50,6 +50,8 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + initNfc(); } /** @@ -81,17 +83,15 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess * guarantee that this activity starts when receiving a beamed message. For now, this code * uses the tag dispatch system. */ - // get public keyring as byte array - long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri); try { - mSharedKeyringBytes = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId).getEncoded(); + // get public keyring as byte array + mSharedKeyringBytes = ProviderHelper.getPGPKeyRing(this, mDataUri).getEncoded(); NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME, mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); return msg; } catch(IOException e) { - // not much trouble, but leave a note - Log.e(Constants.TAG, "Error parsing keyring: ", e); + Log.e(Constants.TAG, "Error parsing keyring", e); return null; } } @@ -114,8 +114,8 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess public void handleMessage(Message msg) { switch (msg.what) { case NFC_SENT: - Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG) - .show(); + AppMsg.makeText(ViewKeyActivityJB.this, R.string.nfc_successfull, + AppMsg.STYLE_INFO).show(); break; } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index 830c5fcae..010124862 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -81,9 +81,6 @@ public class ViewKeyMainFragment extends Fragment implements private Uri mDataUri; - // for activity - private boolean mSecretAvailable = false; - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.view_key_main_fragment, container, false); @@ -231,8 +228,6 @@ public class ViewKeyMainFragment extends Fragment implements mComment.setText(mainUserId[2]); if (data.getInt(INDEX_UNIFIED_HAS_SECRET) != 0) { - mSecretAvailable = true; - mSecretKey.setTextColor(getResources().getColor(R.color.emphasis)); mSecretKey.setText(R.string.secret_key_yes); @@ -247,8 +242,6 @@ public class ViewKeyMainFragment extends Fragment implements } }); } else { - mSecretAvailable = false; - mSecretKey.setTextColor(Color.BLACK); mSecretKey.setText(getResources().getString(R.string.secret_key_no)); @@ -337,11 +330,6 @@ public class ViewKeyMainFragment extends Fragment implements } } - /** Returns true if the key current displayed is known to have a secret key. */ - public boolean isSecretAvailable() { - return mSecretAvailable; - } - private void encryptToContact(Uri dataUri) { // TODO preselect from uri? should be feasible without trivial query long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); diff --git a/OpenPGP-Keychain/src/main/res/layout/view_key_main_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/view_key_main_fragment.xml index aa48252ce..e3448c39f 100644 --- a/OpenPGP-Keychain/src/main/res/layout/view_key_main_fragment.xml +++ b/OpenPGP-Keychain/src/main/res/layout/view_key_main_fragment.xml @@ -192,8 +192,7 @@ + android:layout_height="wrap_content" /> diff --git a/OpenPGP-Keychain/src/main/res/menu/key_edit.xml b/OpenPGP-Keychain/src/main/res/menu/key_edit.xml deleted file mode 100644 index f9f7f8f0a..000000000 --- a/OpenPGP-Keychain/src/main/res/menu/key_edit.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - \ No newline at end of file