diff options
7 files changed, 350 insertions, 152 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index bc6912f38..3014d7093 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -135,6 +135,15 @@ android:value=".ui.ViewKeyActivity" /> </activity> <activity + android:name=".ui.SafeSlingerActivity" + android:configChanges="orientation|screenSize|keyboardHidden|keyboard" + android:label="@string/title_exchange_keys" + android:parentActivityName=".ui.KeyListActivity"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".ui.KeyListActivity" /> + </activity> + <activity android:name=".ui.SelectPublicKeyActivity" android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:label="@string/title_select_recipients" diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index c05393f6d..ba03400d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -206,7 +206,6 @@ public class KeyListActivity extends DrawerActivity { // start service with intent startService(intent); - } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 0b28a2594..eba16e55d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -115,10 +115,6 @@ public class KeyListFragment extends LoaderFragment boolean hideMenu = false; - Long mExchangeMasterKeyId = null; - - private static final int REQUEST_CODE_SAFE_SLINGER = 2; - /** * Load custom layout with StickyListView from library */ @@ -603,7 +599,9 @@ public class KeyListFragment extends LoaderFragment @Override public void onClick(View v) { if (holder.mMasterKeyId != null) { - startExchange(holder.mMasterKeyId); + Intent safeSlingerIntent = new Intent(getActivity(), SafeSlingerActivity.class); + safeSlingerIntent.putExtra(SafeSlingerActivity.EXTRA_MASTER_KEY_ID, holder.mMasterKeyId); + startActivity(safeSlingerIntent); } } }); @@ -842,136 +840,6 @@ public class KeyListFragment extends LoaderFragment } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_CODE_SAFE_SLINGER) { - if (resultCode == ExchangeActivity.RESULT_EXCHANGE_CANCELED) { - return; - } - - final FragmentActivity activity = getActivity(); - - // Message is received after importing is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( - activity, - getString(R.string.progress_importing), - ProgressDialog.STYLE_HORIZONTAL, - true) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - if (returnData == null) { - return; - } - final ImportKeyResult result = - returnData.getParcelable(OperationResult.EXTRA_RESULT); - if (result == null) { - Log.e(Constants.TAG, "result == null"); - return; - } - - if (!result.success()) { - result.createNotify(activity).show(); - return; - } - - if (mExchangeMasterKeyId == null) { - return; - } - - Intent certifyIntent = new Intent(activity, MultiCertifyKeyActivity.class); - certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_RESULT, result); - certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_KEY_IDS, result.getImportedMasterKeyIds()); - certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, mExchangeMasterKeyId); - startActivityForResult(certifyIntent, KeyListActivity.REQUEST_CODE_RESULT_TO_LIST); - - mExchangeMasterKeyId = null; - } - } - }; - - Log.d(Constants.TAG, "importKeys started"); - - // Send all information needed to service to import key in other thread - Intent intent = new Intent(activity, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); - - // instead of giving the entries by Intent extra, cache them into a - // file to prevent Java Binder problems on heavy imports - // read FileImportCache for more info. - try { - // import exchanged keys - ArrayList<ParcelableKeyRing> it = getSlingedKeys(data.getExtras()); - - // We parcel this iteratively into a file - anything we can - // display here, we should be able to import. - ParcelableFileCache<ParcelableKeyRing> cache = - new ParcelableFileCache<ParcelableKeyRing>(activity, "key_import.pcl"); - cache.writeCache(it.size(), it.iterator()); - - // fill values for this action - Bundle bundle = new Bundle(); - intent.putExtra(KeychainIntentService.EXTRA_DATA, bundle); - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(activity); - - // start service with intent - activity.startService(intent); - } catch (IOException e) { - Log.e(Constants.TAG, "Problem writing cache file", e); - Notify.showNotify(activity, "Problem writing cache file!", Notify.Style.ERROR); - } - } - - super.onActivityResult(requestCode, resultCode, data); - } - - private static ArrayList<ParcelableKeyRing> getSlingedKeys(Bundle extras) { - - ArrayList<ParcelableKeyRing> list = new ArrayList<ParcelableKeyRing>(); - - if (extras != null) { - byte[] d; - int i = 0; - do { - d = extras.getByteArray(ExchangeConfig.extra.MEMBER_DATA + i); - if (d != null) { - list.add(new ParcelableKeyRing(d)); - i++; - } - } while (d != null); - } - - return list; - - } - - private void startExchange(long masterKeyId) { - mExchangeMasterKeyId = masterKeyId; - // retrieve public key blob and start SafeSlinger - Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId); - try { - byte[] keyBlob = (byte[]) new ProviderHelper(getActivity()).getGenericData( - uri, KeychainContract.KeyRingData.KEY_RING_DATA, ProviderHelper.FIELD_TYPE_BLOB); - - Intent slingerIntent = new Intent(getActivity(), ExchangeActivity.class); - slingerIntent.putExtra(ExchangeConfig.extra.USER_DATA, keyBlob); - slingerIntent.putExtra(ExchangeConfig.extra.HOST_NAME, Constants.SAFESLINGER_SERVER); - startActivityForResult(slingerIntent, REQUEST_CODE_SAFE_SLINGER); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "personal key not found", e); - } - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java index b8e3dd590..36ea453c5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java @@ -17,27 +17,250 @@ package org.sufficientlysecure.keychain.ui; +import android.annotation.TargetApi; +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.support.v4.app.FragmentActivity; import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.NumberPicker; +import android.widget.Spinner; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; +import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ParcelableFileCache; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import edu.cmu.cylab.starslinger.exchange.ExchangeActivity; +import edu.cmu.cylab.starslinger.exchange.ExchangeConfig; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) public class SafeSlingerActivity extends ActionBarActivity { + private static final int REQUEST_CODE_SAFE_SLINGER = 211; + + public static final String EXTRA_MASTER_KEY_ID = "master_key_id"; + + private long mMasterKeyId; + private int mSelectedNumber; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.safe_slinger_activity); - NumberPicker numberPicker = (NumberPicker) findViewById(R.id.safe_slinger_number_picker); + mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, 0); + + // NOTE: there are two versions of this layout, for API >= 11 and one for < 11 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + NumberPicker picker = (NumberPicker) findViewById(R.id.safe_slinger_picker); + picker.setMinValue(2); + picker.setMaxValue(10); + picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mSelectedNumber = newVal; + } + }); + } else { + Spinner spinner = (Spinner) findViewById(R.id.safe_slinger_spinner); + + List<String> list = new ArrayList<String>(); + list.add("2"); + list.add("3"); + list.add("4"); + list.add("5"); + list.add("6"); + list.add("7"); + list.add("8"); + list.add("9"); + list.add("10"); + + ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, + android.R.layout.simple_spinner_item, list); + dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(dataAdapter); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + mSelectedNumber = position + 2; + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + + } + }); + } + + ImageView button = (ImageView) findViewById(R.id.safe_slinger_button_image); + button.setColorFilter(getResources().getColor(R.color.tertiary_text_light), + PorterDuff.Mode.SRC_IN); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startExchange(mMasterKeyId); + } + }); + } + + private void startExchange(long masterKeyId) { + // retrieve public key blob and start SafeSlinger + Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId); + try { + byte[] keyBlob = (byte[]) new ProviderHelper(this).getGenericData( + uri, KeychainContract.KeyRingData.KEY_RING_DATA, ProviderHelper.FIELD_TYPE_BLOB); + + Intent slingerIntent = new Intent(this, ExchangeActivity.class); + slingerIntent.putExtra(ExchangeConfig.extra.USER_DATA, keyBlob); + slingerIntent.putExtra(ExchangeConfig.extra.HOST_NAME, Constants.SAFESLINGER_SERVER); + startActivityForResult(slingerIntent, REQUEST_CODE_SAFE_SLINGER); + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "personal key not found", e); + } + } + + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_SAFE_SLINGER) { + if (resultCode == ExchangeActivity.RESULT_EXCHANGE_CANCELED) { + return; + } + + final FragmentActivity activity = SafeSlingerActivity.this; + + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + activity, + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL, + true) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; + } + final ImportKeyResult result = + returnData.getParcelable(OperationResult.EXTRA_RESULT); + if (result == null) { + Log.e(Constants.TAG, "result == null"); + return; + } + + if (!result.success()) { +// result.createNotify(activity).show(); + // only return if no success... + Intent data = new Intent(); + data.putExtras(returnData); + setResult(RESULT_OK, data); + finish(); + return; + } + +// if (mExchangeMasterKeyId == null) { +// return; +// } + + Intent certifyIntent = new Intent(activity, MultiCertifyKeyActivity.class); + certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_RESULT, result); + certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_KEY_IDS, result.getImportedMasterKeyIds()); + certifyIntent.putExtra(MultiCertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, mMasterKeyId); + startActivityForResult(certifyIntent, KeyListActivity.REQUEST_CODE_RESULT_TO_LIST); + +// mExchangeMasterKeyId = null; + } + } + }; + + Log.d(Constants.TAG, "importKeys started"); + + // Send all information needed to service to import key in other thread + Intent intent = new Intent(activity, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); + + // instead of giving the entries by Intent extra, cache them into a + // file to prevent Java Binder problems on heavy imports + // read FileImportCache for more info. + try { + // import exchanged keys + ArrayList<ParcelableKeyRing> it = getSlingedKeys(data.getExtras()); + + // We parcel this iteratively into a file - anything we can + // display here, we should be able to import. + ParcelableFileCache<ParcelableKeyRing> cache = + new ParcelableFileCache<ParcelableKeyRing>(activity, "key_import.pcl"); + cache.writeCache(it.size(), it.iterator()); + + // fill values for this action + Bundle bundle = new Bundle(); + intent.putExtra(KeychainIntentService.EXTRA_DATA, bundle); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(activity); + + // start service with intent + activity.startService(intent); + } catch (IOException e) { + Log.e(Constants.TAG, "Problem writing cache file", e); + Notify.showNotify(activity, "Problem writing cache file!", Notify.Style.ERROR); + } + } else { + // give everything else down to KeyListActivity! + setResult(resultCode, data); + finish(); + } + } + + private static ArrayList<ParcelableKeyRing> getSlingedKeys(Bundle extras) { + ArrayList<ParcelableKeyRing> list = new ArrayList<ParcelableKeyRing>(); + + if (extras != null) { + byte[] d; + int i = 0; + do { + d = extras.getByteArray(ExchangeConfig.extra.MEMBER_DATA + i); + if (d != null) { + list.add(new ParcelableKeyRing(d)); + i++; + } + } while (d != null); + } - numberPicker.setDisplayedValues(new String[]{"2","3","4","5","6","7","8","9","10"}); - numberPicker.setValue(0); -// numberPicker.setMaxValue(8); -// numberPicker.setMinValue(0); + return list; } } diff --git a/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml b/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml new file mode 100644 index 000000000..5e8e5aa5f --- /dev/null +++ b/OpenKeychain/src/main/res/layout-v11/safe_slinger_activity.xml @@ -0,0 +1,65 @@ +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingLeft="16dp" + android:paddingRight="16dp"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="4dp" + android:layout_marginTop="14dp" + android:text="bla" /> + + <NumberPicker + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/safe_slinger_picker" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + + <LinearLayout + android:id="@+id/safe_slinger_button" + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:clickable="true" + android:paddingRight="4dp" + style="@style/SelectableItem" + android:orientation="horizontal"> + + <TextView + android:paddingLeft="8dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="0dip" + android:layout_height="match_parent" + android:text="Start exchange" + android:layout_weight="1" + android:gravity="center_vertical" /> + + <!-- separate ImageView required for recoloring --> + <ImageView + android:id="@+id/safe_slinger_button_image" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:padding="8dp" + android:src="@drawable/ic_action_safeslinger" + android:layout_gravity="center_vertical" /> + + </LinearLayout> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginBottom="4dp" + android:background="?android:attr/listDivider" /> + + </LinearLayout> +</ScrollView> diff --git a/OpenKeychain/src/main/res/layout/safe_slinger_activity.xml b/OpenKeychain/src/main/res/layout/safe_slinger_activity.xml index 46d9237ea..e81c21182 100644 --- a/OpenKeychain/src/main/res/layout/safe_slinger_activity.xml +++ b/OpenKeychain/src/main/res/layout/safe_slinger_activity.xml @@ -10,17 +10,56 @@ android:paddingRight="16dp"> <TextView - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="4dp" android:layout_marginTop="14dp" android:text="bla" /> - <NumberPicker - android:layout_width="wrap_content" + <Spinner + android:layout_width="match_parent" android:layout_height="wrap_content" - android:id="@+id/safe_slinger_number_picker" /> + android:id="@+id/safe_slinger_spinner" /> - </LinearLayout> + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" /> + + <LinearLayout + android:id="@+id/safe_slinger_button" + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:clickable="true" + android:paddingRight="4dp" + style="@style/SelectableItem" + android:orientation="horizontal"> + + <TextView + android:paddingLeft="8dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="0dip" + android:layout_height="match_parent" + android:text="Start exchange" + android:layout_weight="1" + android:gravity="center_vertical" /> + + <!-- separate ImageView required for recoloring --> + <ImageView + android:id="@+id/safe_slinger_button_image" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:padding="8dp" + android:src="@drawable/ic_action_safeslinger" + android:layout_gravity="center_vertical" /> + </LinearLayout> + + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginBottom="4dp" + android:background="?android:attr/listDivider" /> + + </LinearLayout> </ScrollView> diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 656f3b5cd..87c0acd6a 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ <string name="title_help">"Help"</string> <string name="title_log_display">"Log"</string> <string name="title_create_key">"Create Key"</string> + <string name="title_exchange_keys">"Exchange Keys"</string> <!-- section --> <string name="section_user_ids">"Identities"</string> @@ -238,7 +239,6 @@ <string name="select_key_to_certify">"Please select a key to be used for certification!"</string> <string name="key_too_big_for_sharing">"Key is too big to be shared this way!"</string> <string name="text_copied_to_clipboard">"Text has been copied to the clipboard!"</string> - <string name="select_key_for_exchange">"Please select a key to be used for secure exchange!"</string> <!-- errors @@ -283,12 +283,7 @@ <string name="decrypt_invalid_button">"I understand the risks, display it!"</string> <!-- Add keys --> - <string name="add_keys_section_secure_exchange">"Exchange"</string> - <string name="add_keys_section_secure_add">"Add"</string> <string name="add_keys_my_key">"My key:"</string> - <string name="add_keys_start_exchange">"Start exchange"</string> - <string name="add_keys_qr_code">"Scan QR Code"</string> - <string name="add_keys_nfc">"Receive via NFC"</string> <!-- progress dialogs, usually ending in '…' --> <string name="progress_done">"Done."</string> |