list trust ids in ShowKeyFragment

This commit is contained in:
Vincent Breitmoser
2016-11-16 15:52:40 +01:00
parent c7bb6a7bc0
commit 31ef4c4789
10 changed files with 418 additions and 16 deletions

View File

@@ -128,6 +128,9 @@ public class KeychainContract {
public static final String BASE_API_APPS = "api_apps";
public static final String PATH_ALLOWED_KEYS = "allowed_keys";
public static final String PATH_BY_PACKAGE_NAME = "by_package_name";
public static final String PATH_BY_KEY_ID = "by_key_id";
public static final String BASE_TRUST_IDENTITIES = "trust_ids";
public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns {
@@ -345,24 +348,12 @@ public class KeychainContract {
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
.appendPath(BASE_TRUST_IDENTITIES).build();
/**
* Use if multiple items get returned
*/
public static final String CONTENT_TYPE
= "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.trust_ids";
/**
* Use if a single item is returned
*/
public static final String CONTENT_ITEM_TYPE
= "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.trust_ids";
public static Uri buildByPackageNameUri(String packageName) {
return CONTENT_URI.buildUpon().appendEncodedPath(packageName).build();
public static Uri buildByKeyUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(PATH_BY_KEY_ID).appendPath(uri.getPathSegments().get(1)).build();
}
public static Uri buildByPackageNameAndTrustIdUri(String packageName, String trustId) {
return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendEncodedPath(trustId).build();
public static Uri buildByPackageNameAndTrustId(String packageName, String trustId) {
return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName).appendPath(trustId).build();
}
}

View File

@@ -79,6 +79,10 @@ public class KeychainProvider extends ContentProvider {
private static final int UPDATED_KEYS = 500;
private static final int UPDATED_KEYS_SPECIFIC = 501;
private static final int TRUST_IDS_BY_MASTER_KEY_ID = 601;
private static final int TRUST_IDS_BY_PACKAGE_NAME = 602;
private static final int TRUST_IDS_BY_PACKAGE_NAME_AND_TRUST_ID = 603;
protected UriMatcher mUriMatcher;
/**
@@ -191,6 +195,22 @@ public class KeychainProvider extends ContentProvider {
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ KeychainContract.PATH_ALLOWED_KEYS, API_ALLOWED_KEYS);
/**
* Trust Identity access
*
* <pre>
* trust_ids/by_key_id/_
*
* </pre>
*/
matcher.addURI(authority, KeychainContract.BASE_TRUST_IDENTITIES + "/" +
KeychainContract.PATH_BY_KEY_ID + "/*", TRUST_IDS_BY_MASTER_KEY_ID);
matcher.addURI(authority, KeychainContract.BASE_TRUST_IDENTITIES + "/" +
KeychainContract.PATH_BY_PACKAGE_NAME + "/*", TRUST_IDS_BY_PACKAGE_NAME);
matcher.addURI(authority, KeychainContract.BASE_TRUST_IDENTITIES + "/" +
KeychainContract.PATH_BY_PACKAGE_NAME + "/*/*", TRUST_IDS_BY_PACKAGE_NAME_AND_TRUST_ID);
/**
* to access table containing last updated dates of keys
*/
@@ -636,6 +656,45 @@ public class KeychainProvider extends ContentProvider {
break;
}
case TRUST_IDS_BY_MASTER_KEY_ID:
case TRUST_IDS_BY_PACKAGE_NAME:
case TRUST_IDS_BY_PACKAGE_NAME_AND_TRUST_ID: {
if (selection != null || selectionArgs != null) {
throw new UnsupportedOperationException();
}
HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(ApiTrustIdentity._ID, "oid AS " + ApiTrustIdentity._ID);
projectionMap.put(ApiTrustIdentity.PACKAGE_NAME, ApiTrustIdentity.PACKAGE_NAME);
projectionMap.put(ApiTrustIdentity.IDENTIFIER, ApiTrustIdentity.IDENTIFIER);
projectionMap.put(ApiTrustIdentity.MASTER_KEY_ID, ApiTrustIdentity.MASTER_KEY_ID);
projectionMap.put(ApiTrustIdentity.LAST_UPDATED, ApiTrustIdentity.LAST_UPDATED);
qb.setProjectionMap(projectionMap);
qb.setTables(Tables.API_TRUST_IDENTITIES);
if (match == TRUST_IDS_BY_MASTER_KEY_ID) {
long masterKeyId = Long.parseLong(uri.getLastPathSegment());
selection = Tables.API_TRUST_IDENTITIES + "." + ApiTrustIdentity.MASTER_KEY_ID + " = ?";
selectionArgs = new String[] { Long.toString(masterKeyId) };
} else if (match == TRUST_IDS_BY_PACKAGE_NAME) {
String packageName = uri.getPathSegments().get(2);
selection = Tables.API_TRUST_IDENTITIES + "." + ApiTrustIdentity.PACKAGE_NAME + " = ?";
selectionArgs = new String[] { packageName };
} else { // TRUST_IDS_BY_PACKAGE_NAME_AND_TRUST_ID
String packageName = uri.getPathSegments().get(2);
String trustId = uri.getPathSegments().get(3);
selection = Tables.API_TRUST_IDENTITIES + "." + ApiTrustIdentity.PACKAGE_NAME + " = ? AND " +
Tables.API_TRUST_IDENTITIES + "." + ApiTrustIdentity.IDENTIFIER + " = ?";
selectionArgs = new String[] { packageName, trustId };
}
break;
}
case UPDATED_KEYS:
case UPDATED_KEYS_SPECIFIC: {
HashMap<String, String> projectionMap = new HashMap<>();

View File

@@ -28,6 +28,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
@@ -285,6 +286,9 @@ public class KeychainExternalProvider extends ContentProvider implements SimpleC
if (cursor != null) {
// Tell the cursor what uri to watch, so it knows when its source data changes
cursor.setNotificationUri(getContext().getContentResolver(), uri);
if (Constants.DEBUG_LOG_DB_QUERIES) {
DatabaseUtils.dumpCursor(cursor);
}
}
Log.d(Constants.TAG,

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2016 Vincent Breitmoser <look@my.amazin.horse>
*
* 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 java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.v4.content.CursorLoader;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiTrustIdentity;
public class TrustIdsAdapter extends CursorAdapter {
private static final String[] TRUST_IDS_PROJECTION = new String[] {
ApiTrustIdentity._ID,
ApiTrustIdentity.PACKAGE_NAME,
ApiTrustIdentity.IDENTIFIER,
};
private static final int INDEX_PACKAGE_NAME = 1;
private static final int INDEX_TRUST_ID = 2;
protected LayoutInflater mInflater;
private HashMap<String, Drawable> appIconCache = new HashMap<>();
public TrustIdsAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String packageName = cursor.getString(INDEX_PACKAGE_NAME);
String trustId = cursor.getString(INDEX_TRUST_ID);
TextView vTrustId = (TextView) view.findViewById(R.id.trust_id_name);
ImageView vAppIcon = (ImageView) view.findViewById(R.id.trust_id_app_icon);
Drawable drawable = getDrawableForPackageName(packageName);
vTrustId.setText(trustId);
vAppIcon.setImageDrawable(drawable);
}
private Drawable getDrawableForPackageName(String packageName) {
if (appIconCache.containsKey(packageName)) {
return appIconCache.get(packageName);
}
PackageManager pm = mContext.getPackageManager();
try {
ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
Drawable appIcon = pm.getApplicationIcon(ai);
appIconCache.put(packageName, appIcon);
return appIcon;
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
public static CursorLoader createLoader(Context context, Uri dataUri) {
Uri baseUri = ApiTrustIdentity.buildByKeyUri(dataUri);
return new CursorLoader(context, baseUri, TrustIdsAdapter.TRUST_IDS_PROJECTION, null, null, null);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.view_key_trust_id_item, parent, false);
}
}

View File

@@ -37,11 +37,14 @@ import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyserverStatusPresenter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.SystemContactPresenter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.TrustIdsPresenter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.ViewKeyMvpView;
import org.sufficientlysecure.keychain.ui.keyview.view.IdentitiesCardView;
import org.sufficientlysecure.keychain.ui.keyview.view.KeyHealthView;
import org.sufficientlysecure.keychain.ui.keyview.view.KeyserverStatusView;
import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView;
import org.sufficientlysecure.keychain.ui.keyview.view.TrustIdsIdCardView;
import org.sufficientlysecure.keychain.util.Preferences;
public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView {
@@ -54,10 +57,14 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView {
private static final int LOADER_ID_LINKED_CONTACT = 2;
private static final int LOADER_ID_SUBKEY_STATUS = 3;
private static final int LOADER_ID_KEYSERVER_STATUS = 4;
private static final int LOADER_ID_TRUST_IDS = 5;
private IdentitiesCardView mIdentitiesCardView;
private IdentitiesPresenter mIdentitiesPresenter;
private TrustIdsIdCardView mTrustIdsCard;
private TrustIdsPresenter mTrustIdsPresenter;
SystemContactCardView mSystemContactCard;
SystemContactPresenter mSystemContactPresenter;
@@ -88,6 +95,8 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView {
mIdentitiesCardView = (IdentitiesCardView) view.findViewById(R.id.card_identities);
mTrustIdsCard = (TrustIdsIdCardView) view.findViewById(R.id.view_key_card_trust_ids);
mSystemContactCard = (SystemContactCardView) view.findViewById(R.id.linked_system_contact_card);
mKeyStatusHealth = (KeyHealthView) view.findViewById(R.id.key_status_health);
mKeyStatusKeyserver = (KeyserverStatusView) view.findViewById(R.id.key_status_keyserver);
@@ -117,6 +126,10 @@ public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView {
mKeyserverStatusPresenter = new KeyserverStatusPresenter(
getContext(), mKeyStatusKeyserver, LOADER_ID_KEYSERVER_STATUS, masterKeyId, mIsSecret);
mKeyserverStatusPresenter.startLoader(getLoaderManager());
mTrustIdsPresenter = new TrustIdsPresenter(
getContext(), mTrustIdsCard, LOADER_ID_TRUST_IDS, masterKeyId, false);
mTrustIdsPresenter.startLoader(getLoaderManager());
}
@Override

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2017 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.keyview.presenter;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.adapter.TrustIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
public class TrustIdsPresenter implements LoaderCallbacks<Cursor> {
private final Context context;
private final TrustIdsMvpView view;
private final int loaderId;
private final TrustIdsAdapter trustIdsAdapter;
private final long masterKeyId;
private final boolean isSecret;
public TrustIdsPresenter(Context context, TrustIdsMvpView view, int loaderId, long masterKeyId, boolean isSecret) {
this.context = context;
this.view = view;
this.loaderId = loaderId;
this.masterKeyId = masterKeyId;
this.isSecret = isSecret;
trustIdsAdapter = new TrustIdsAdapter(context, null, 0);
view.setTrustIdAdapter(trustIdsAdapter);
view.setTrustIdClickListener(new TrustIdsClickListener() {
@Override
public void onTrustIdItemClick(int position) {
}
});
}
public void startLoader(LoaderManager loaderManager) {
loaderManager.restartLoader(loaderId, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return TrustIdsAdapter.createLoader(context, KeyRings.buildUnifiedKeyRingUri(masterKeyId));
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
trustIdsAdapter.swapCursor(data);
view.showCard(trustIdsAdapter.getCount() > 0);
}
@Override
public void onLoaderReset(Loader loader) {
trustIdsAdapter.swapCursor(null);
}
public interface TrustIdsMvpView {
void setTrustIdAdapter(TrustIdsAdapter trustIdsAdapter);
void showCard(boolean show);
void setTrustIdClickListener(TrustIdsClickListener trustIdsClickListener);
}
public interface TrustIdsClickListener {
void onTrustIdItemClick(int position);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2017 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.keyview.view;
import android.content.Context;
import android.support.v7.widget.CardView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.TrustIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesCardListener;
import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesMvpView;
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsClickListener;
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsMvpView;
import org.sufficientlysecure.keychain.ui.keyview.presenter.TrustIdsPresenter.TrustIdsClickListener;
import org.sufficientlysecure.keychain.ui.keyview.presenter.TrustIdsPresenter.TrustIdsMvpView;
public class TrustIdsIdCardView extends CardView implements TrustIdsMvpView {
private ListView vTrustIds;
private TrustIdsClickListener trustIdsClickListener;
public TrustIdsIdCardView(Context context, AttributeSet attrs) {
super(context, attrs);
View view = LayoutInflater.from(context).inflate(R.layout.trust_ids_card, this, true);
vTrustIds = (ListView) view.findViewById(R.id.view_key_trust_ids);
vTrustIds.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (trustIdsClickListener != null) {
trustIdsClickListener.onTrustIdItemClick(position);
}
}
});
}
@Override
public void setTrustIdAdapter(TrustIdsAdapter trustIdsAdapter) {
vTrustIds.setAdapter(trustIdsAdapter);
}
@Override
public void showCard(boolean show) {
setVisibility(show ? View.VISIBLE : View.GONE);
}
@Override
public void setTrustIdClickListener(TrustIdsClickListener trustIdsClickListener) {
this.trustIdsClickListener = trustIdsClickListener;
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="@style/CardViewHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Known to Apps as" />
<org.sufficientlysecure.keychain.ui.widget.FixedListView
android:id="@+id/view_key_trust_ids"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp" />
</LinearLayout>
</merge>

View File

@@ -51,6 +51,17 @@
</android.support.v7.widget.CardView>
<org.sufficientlysecure.keychain.ui.keyview.view.TrustIdsIdCardView
android:id="@+id/view_key_card_trust_ids"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?attr/colorCardViewBackground"
card_view:cardCornerRadius="4dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
/>
<org.sufficientlysecure.keychain.ui.keyview.view.IdentitiesCardView
android:id="@+id/card_identities"
android:layout_width="match_parent"

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:maxLines="1"
android:padding="8dp"
>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:padding="8dp"
android:id="@+id/trust_id_app_icon"
tools:src="@drawable/apps_k9"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:id="@+id/trust_id_name"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="alice@example.com"
/>
</LinearLayout>