diff options
Diffstat (limited to 'OpenKeychain/src/main/java')
8 files changed, 593 insertions, 33 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/AddKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/AddKeysActivity.java new file mode 100644 index 000000000..ecc72c24d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/AddKeysActivity.java @@ -0,0 +1,464 @@ +/* + * 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.app.ProgressDialog; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; +import android.support.v4.util.LongSparseArray; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.ImageView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.keyimport.Keyserver; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; +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.service.results.ImportKeyResult; +import org.sufficientlysecure.keychain.service.results.OperationResult; +import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; +import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListCloudLoader; +import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.widget.ExchangeKeySpinner; +import org.sufficientlysecure.keychain.ui.widget.KeySpinner; +import org.sufficientlysecure.keychain.util.InputData; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ParcelableFileCache; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +import edu.cmu.cylab.starslinger.exchange.ExchangeActivity; +import edu.cmu.cylab.starslinger.exchange.ExchangeConfig; + +public class AddKeysActivity extends ActionBarActivity implements +        LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { + +    ExchangeKeySpinner mSafeSlingerKeySpinner; +    View mActionSafeSlinger; +    ImageView mActionSafeSlingerIcon; +    View mActionQrCode; +    View mActionSearchCloud; + +    ProviderHelper mProviderHelper; + +    long mExchangeMasterKeyId = Constants.key.none; + +    byte[] mImportBytes; +    private LongSparseArray<ParcelableKeyRing> mCachedKeyData; + + +    private static final int REQUEST_CODE_SAFE_SLINGER = 1; + + +    private static final int LOADER_ID_BYTES = 0; +    private static final int LOADER_ID_CLOUD = 1; + +    @Override +    public void onCreate(Bundle savedInstanceState) { +        super.onCreate(savedInstanceState); + +        mProviderHelper = new ProviderHelper(this); + +        setContentView(R.layout.add_key_activity); + +        mSafeSlingerKeySpinner = (ExchangeKeySpinner) findViewById(R.id.add_keys_safeslinger_key_spinner); +        mActionSafeSlinger = findViewById(R.id.add_keys_safeslinger); +        mActionSafeSlingerIcon = (ImageView) findViewById(R.id.add_keys_safeslinger_icon); +        // make certify image gray, like action icons +        mActionSafeSlingerIcon.setColorFilter(getResources().getColor(R.color.tertiary_text_light), +                PorterDuff.Mode.SRC_IN); +        mActionQrCode = findViewById(R.id.add_keys_qr_code); +        mActionSearchCloud = findViewById(R.id.add_keys_search_cloud); + +        mSafeSlingerKeySpinner.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() { +            @Override +            public void onKeyChanged(long masterKeyId) { +                mExchangeMasterKeyId = masterKeyId; +            } +        }); + +        mActionSafeSlinger.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                startExchange(); +            } +        }); + +        mActionQrCode.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                startQrCode(); +            } +        }); + +        mActionSearchCloud.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                searchCloud(); +            } +        }); + +    } + +    private void startExchange() { +        if (mExchangeMasterKeyId == 0) { +            Notify.showNotify(this, getString(R.string.select_key_for_exchange), +                    Notify.Style.ERROR); +        } else { +            // retrieve public key blob and start SafeSlinger +            Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(mExchangeMasterKeyId); +            try { +                byte[] keyBlob = (byte[]) mProviderHelper.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); +            } +        } +    } + +    private void startQrCode() { + +    } + +    private void searchCloud() { +        Intent importIntent = new Intent(this, ImportKeysActivity.class); +        startActivity(importIntent); +    } + +    @Override +    protected void onActivityResult(int requestCode, int resultCode, Intent data) { +        // if a result has been returned, display a notify +        if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { +            OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); +            result.createNotify(this).show(); +        } else { +            switch (requestCode) { +                case REQUEST_CODE_SAFE_SLINGER: +                    switch (resultCode) { +                        case ExchangeActivity.RESULT_EXCHANGE_OK: +                            // import exchanged keys +                            mImportBytes = getSlingedKeys(data); +                            getSupportLoaderManager().restartLoader(LOADER_ID_BYTES, null, this); +//                            Intent importIntent = new Intent(this, ImportKeysActivity.class); +//                            importIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY); +//                            importIntent.putExtra(ImportKeysActivity.EXTRA_KEY_BYTES, getSlingedKeys(data)); +//                            startActivity(importIntent); +                            break; +                        case ExchangeActivity.RESULT_EXCHANGE_CANCELED: +                            // handle canceled result +                            // ... +                            break; +                    } +                    break; +            } +            super.onActivityResult(requestCode, resultCode, data); +        } +    } + +    private static byte[] getSlingedKeys(Intent data) { +        ByteArrayOutputStream out = new ByteArrayOutputStream(); + +        Bundle extras = data.getExtras(); +        if (extras != null) { +            byte[] d; +            int i = 0; +            do { +                d = extras.getByteArray(ExchangeConfig.extra.MEMBER_DATA + i); +                if (d != null) { +                    try { +                        out.write(d); +                    } catch (IOException e) { +                        Log.e(Constants.TAG, "IOException", e); +                    } +                    i++; +                } +            } while (d != null); +        } + +        return out.toByteArray(); +    } + +    @Override +    public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) { +        switch (id) { +            case LOADER_ID_BYTES: { +                InputData inputData = new InputData(new ByteArrayInputStream(mImportBytes), mImportBytes.length); +                return new ImportKeysListLoader(this, inputData); +            } +            case LOADER_ID_CLOUD: { +//                ImportKeysListFragment.CloudLoaderState ls = (ImportKeysListFragment.CloudLoaderState) mLoaderState; +//                return new ImportKeysListCloudLoader(this, ls.mServerQuery, ls.mCloudPrefs); +            } + +            default: +                return null; +        } +    } + +    @Override +    public void onLoadFinished(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader, AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) { + +        Log.d(Constants.TAG, "data: " + data.getResult()); + +        // swap in the real data! +//        mAdapter.setData(data.getResult()); +//        mAdapter.notifyDataSetChanged(); +// +//        setListAdapter(mAdapter); +// +//        // The list should now be shown. +//        if (isResumed()) { +//            setListShown(true); +//        } else { +//            setListShownNoAnimation(true); +//        } + +        Exception error = data.getError(); + +        // free old cached key data +        mCachedKeyData = null; + + +        // TODO: Use parcels!!!!!!!!!!!!!!! +        switch (loader.getId()) { +            case LOADER_ID_BYTES: + +                if (error == null) { +                    // No error +                    mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings(); +                } else if (error instanceof ImportKeysListLoader.NoValidKeysException) { +                    Notify.showNotify(this, R.string.error_import_no_valid_keys, Notify.Style.ERROR); +                } else if (error instanceof ImportKeysListLoader.NonPgpPartException) { +                    Notify.showNotify(this, +                            ((ImportKeysListLoader.NonPgpPartException) error).getCount() + " " + getResources(). +                                    getQuantityString(R.plurals.error_import_non_pgp_part, +                                            ((ImportKeysListLoader.NonPgpPartException) error).getCount()), +                            Notify.Style.OK +                    ); +                } else { +                    Notify.showNotify(this, R.string.error_generic_report_bug, Notify.Style.ERROR); +                } +                break; + +            case LOADER_ID_CLOUD: + +                if (error == null) { +                    // No error +                } else if (error instanceof Keyserver.QueryTooShortException) { +                    Notify.showNotify(this, R.string.error_query_too_short, Notify.Style.ERROR); +                } else if (error instanceof Keyserver.TooManyResponsesException) { +                    Notify.showNotify(this, R.string.error_too_many_responses, Notify.Style.ERROR); +                } else if (error instanceof Keyserver.QueryTooShortOrTooManyResponsesException) { +                    Notify.showNotify(this, R.string.error_too_short_or_too_many_responses, Notify.Style.ERROR); +                } else if (error instanceof Keyserver.QueryFailedException) { +                    Log.d(Constants.TAG, +                            "Unrecoverable keyserver query error: " + error.getLocalizedMessage()); +                    String alert = this.getString(R.string.error_searching_keys); +                    alert = alert + " (" + error.getLocalizedMessage() + ")"; +                    Notify.showNotify(this, alert, Notify.Style.ERROR); +                } +                break; + +            default: +                break; +        } + +        importKeys(); +    } + +    @Override +    public void onLoaderReset(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader) { +        switch (loader.getId()) { +            case LOADER_ID_BYTES: +                // Clear the data in the adapter. +//                mAdapter.clear(); +                break; +            case LOADER_ID_CLOUD: +                // Clear the data in the adapter. +//                mAdapter.clear(); +                break; +            default: +                break; +        } +    } + +    public ParcelableFileCache.IteratorWithSize<ParcelableKeyRing> getSelectedData() { +        return new ParcelableFileCache.IteratorWithSize<ParcelableKeyRing>() { +            int i = 0; + +            @Override +            public int getSize() { +                return mCachedKeyData.size(); +            } + +            @Override +            public boolean hasNext() { +                return (mCachedKeyData.get(i + 1) != null); +            } + +            @Override +            public ParcelableKeyRing next() { +                ParcelableKeyRing key = mCachedKeyData.get(i); +                i++; +                return key; +            } + +            @Override +            public void remove() { +                mCachedKeyData.remove(i); +            } +        }; +    } + +    public void importKeys() { +        // Message is received after importing is done in KeychainIntentService +        KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( +                this, +                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 (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction()) +//                            || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { +//                        Intent intent = new Intent(); +//                        intent.putExtra(ImportKeyResult.EXTRA_RESULT, result); +//                        ImportKeysActivity.this.setResult(RESULT_OK, intent); +//                        ImportKeysActivity.this.finish(); +//                        return; +//                    } +//                    if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) { +//                        ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); +//                        ImportKeysActivity.this.finish(); +//                        return; +//                    } + +                    result.createNotify(AddKeysActivity.this).show(); +                } +            } +        }; + +//        ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState(); +//        if (importBytes != null) { +            Log.d(Constants.TAG, "importKeys started"); + +            // Send all information needed to service to import key in other thread +            Intent intent = new Intent(this, KeychainIntentService.class); + +            intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); + +            // fill values for this action +            Bundle data = new Bundle(); + +            // get DATA from selected key entries +//            ParcelableFileCache.IteratorWithSize<ParcelableKeyRing> selectedEntries = mListFragment.getSelectedData(); + +            // 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 { +                // We parcel this iteratively into a file - anything we can +                // display here, we should be able to import. +                ParcelableFileCache<ParcelableKeyRing> cache = +                        new ParcelableFileCache<ParcelableKeyRing>(this, "key_import.pcl"); +                cache.writeCache(getSelectedData()); + +                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); +            } catch (IOException e) { +                Log.e(Constants.TAG, "Problem writing cache file", e); +                Notify.showNotify(this, "Problem writing cache file!", Notify.Style.ERROR); +            } +//        } else if (ls instanceof ImportKeysListFragment.CloudLoaderState) { +//            ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls; +// +//            // Send all information needed to service to query keys in other thread +//            Intent intent = new Intent(this, KeychainIntentService.class); +// +//            intent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); +// +//            // fill values for this action +//            Bundle data = new Bundle(); +// +//            data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, sls.mCloudPrefs.keyserver); +// +//            // get selected key entries +//            ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedEntries(); +//            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 { +//            Notify.showNotify(this, R.string.error_nothing_import, Notify.Style.ERROR); +//        } +    } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java index 7132518ae..da46de486 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java @@ -82,7 +82,7 @@ public class DrawerActivity extends ActionBarActivity {          }          NavItem mItemIconTexts[] = new NavItem[]{ -                new NavItem(R.drawable.ic_action_person, getString(R.string.nav_keys)), +                new NavItem(R.drawable.ic_action_accounts, getString(R.string.nav_keys)),                  new NavItem(R.drawable.ic_action_secure, getString(R.string.nav_encrypt_text)),                  new NavItem(R.drawable.ic_action_secure, getString(R.string.nav_encrypt_files)),                  new NavItem(R.drawable.ic_action_not_secure, getString(R.string.nav_decrypt)), 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 efad2e45d..002f85e5d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -97,7 +97,6 @@ public class ImportKeysActivity extends ActionBarActivity {      private SlidingTabLayout mSlidingTabLayout;      private PagerTabStripAdapter mTabsAdapter; -    public static final int VIEW_PAGER_HEIGHT = 64; // dp      private static final int ALL_TABS = -1;      private static final int TAB_CLOUD = 0; @@ -270,10 +269,6 @@ public class ImportKeysActivity extends ActionBarActivity {          mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {              @Override              public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { -                // resize view pager back to 64 if keyserver settings have been collapsed -                if (getViewPagerHeight() > VIEW_PAGER_HEIGHT) { -                    resizeViewPager(VIEW_PAGER_HEIGHT); -                }              }              @Override @@ -339,18 +334,6 @@ public class ImportKeysActivity extends ActionBarActivity {          getSupportFragmentManager().executePendingTransactions();      } -    public void resizeViewPager(int dp) { -        ViewGroup.LayoutParams params = mViewPager.getLayoutParams(); -        params.height = FormattingUtils.dpToPx(this, dp); -        // update layout after operations -        mSlidingTabLayout.setViewPager(mViewPager); -    } - -    public int getViewPagerHeight() { -        ViewGroup.LayoutParams params = mViewPager.getLayoutParams(); -        return FormattingUtils.pxToDp(this, params.height); -    } -      private String getFingerprintFromUri(Uri dataUri) {          String fingerprint = dataUri.toString().split(":")[1].toLowerCase(Locale.ENGLISH);          Log.d(Constants.TAG, "fingerprint: " + fingerprint); 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 f06531b01..5eef319c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -84,7 +84,7 @@ public class KeyListActivity extends DrawerActivity {      public boolean onOptionsItemSelected(MenuItem item) {          switch (item.getItemId()) {              case R.id.menu_key_list_add: -                importKeys(); +                addKeys();                  return true;              case R.id.menu_key_list_create: @@ -139,8 +139,8 @@ public class KeyListActivity extends DrawerActivity {          }      } -    private void importKeys() { -        Intent intent = new Intent(this, ImportKeysActivity.class); +    private void addKeys() { +        Intent intent = new Intent(this, AddKeysActivity.class);          startActivityForResult(intent, 0);      } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 07f6529f1..29273300a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -84,13 +84,16 @@ public class CertifyKeySpinner extends KeySpinner {      @Override      public void onLoadFinished(Loader<Cursor> loader, Cursor data) {          super.onLoadFinished(loader, data); -        // If there is only one choice, pick it by default -        if (mAdapter.getCount() == 2) { -            setSelection(1); + +        if (loader.getId() == LOADER_ID) { +            // If there is only one choice, pick it by default +            if (mAdapter.getCount() == 2) { +                setSelection(1); +            } +            mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY); +            mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); +            mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED);          } -        mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY); -        mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); -        mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED);      }      @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ExchangeKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ExchangeKeySpinner.java new file mode 100644 index 000000000..e31d14d48 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ExchangeKeySpinner.java @@ -0,0 +1,100 @@ +/* + * 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.widget; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.util.AttributeSet; +import android.widget.ImageView; + +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; + +public class ExchangeKeySpinner extends KeySpinner { +    public ExchangeKeySpinner(Context context) { +        super(context); +    } + +    public ExchangeKeySpinner(Context context, AttributeSet attrs) { +        super(context, attrs); +    } + +    public ExchangeKeySpinner(Context context, AttributeSet attrs, int defStyle) { +        super(context, attrs, defStyle); +    } + +    @Override +    public Loader<Cursor> onCreateLoader(int loaderId, Bundle data) { +        // This is called when a new Loader needs to be created. This +        // sample only has one Loader, so we don't care about the ID. +        Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri(); + +        // These are the rows that we will retrieve. +        String[] projection = new String[]{ +                KeychainContract.KeyRings._ID, +                KeychainContract.KeyRings.MASTER_KEY_ID, +                KeychainContract.KeyRings.KEY_ID, +                KeychainContract.KeyRings.USER_ID, +                KeychainContract.KeyRings.IS_REVOKED, +                KeychainContract.KeyRings.IS_EXPIRED, +                KeychainContract.KeyRings.HAS_ANY_SECRET +        }; + +        String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1"; + +        // Now create and return a CursorLoader that will take care of +        // creating a Cursor for the data being displayed. +        return new CursorLoader(getContext(), baseUri, projection, where, null, null); +    } + +    private int mIndexIsRevoked, mIndexIsExpired; + +    @Override +    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { +        super.onLoadFinished(loader, data); + +        if (loader.getId() == LOADER_ID) { +            // If there is only one choice, pick it by default +            if (mAdapter.getCount() == 2) { +                setSelection(1); +            } +            mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); +            mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); +        } +    } + +    @Override +    boolean setStatus(Context context, Cursor cursor, ImageView statusView) { +        if (cursor.getInt(mIndexIsRevoked) != 0) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_REVOKED); +            return false; +        } +        if (cursor.getInt(mIndexIsExpired) != 0) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_EXPIRED); +            return false; +        } + +        // valid key +        return true; +    } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index bb4ae3ab6..7ec6ffe95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -50,6 +50,9 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader      protected SelectKeyAdapter mAdapter = new SelectKeyAdapter();      protected OnKeyChangedListener mListener; +    // this shall note collide with other loaders inside the activity +    protected int LOADER_ID = 2343; +      public KeySpinner(Context context) {          super(context);          initView(); @@ -101,7 +104,7 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader      public void reload() {          if (getContext() instanceof FragmentActivity) { -            ((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(0, null, this); +            ((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(LOADER_ID, null, this);          } else {              Log.e(Constants.TAG, "KeySpinner must be attached to FragmentActivity, this is " + getContext().getClass());          } @@ -109,12 +112,16 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader      @Override      public void onLoadFinished(Loader<Cursor> loader, Cursor data) { -        mAdapter.swapCursor(data); +        if (loader.getId() == LOADER_ID) { +            mAdapter.swapCursor(data); +        }      }      @Override      public void onLoaderReset(Loader<Cursor> loader) { -        mAdapter.swapCursor(null); +        if (loader.getId() == LOADER_ID) { +            mAdapter.swapCursor(null); +        }      }      public long getSelectedKeyId() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index ce1f7bb44..2f002d470 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -73,9 +73,12 @@ public class SignKeySpinner extends KeySpinner {      @Override      public void onLoadFinished(Loader<Cursor> loader, Cursor data) {          super.onLoadFinished(loader, data); -        mIndexHasSign = data.getColumnIndex(KeychainContract.KeyRings.HAS_SIGN); -        mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); -        mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); + +        if (loader.getId() == LOADER_ID) { +            mIndexHasSign = data.getColumnIndex(KeychainContract.KeyRings.HAS_SIGN); +            mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); +            mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); +        }      }      @Override  | 
