From 438ccd480e316582617e834a22d0f4c2815aa26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 29 May 2013 13:57:28 +0200 Subject: Check if passphrase is needed in PassphraseCacheService, extend documentation --- .../keychain/service/PassphraseCacheService.java | 52 +++++++++++++--------- 1 file changed, 30 insertions(+), 22 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index d11b8e92a..6a4c8a0af 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -48,6 +48,12 @@ import android.os.Messenger; import android.os.RemoteException; import android.util.Log; +/** + * This service runs in its own process, but is available to all other processes as the main + * passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for + * convenience. + * + */ public class PassphraseCacheService extends Service { public static final String TAG = Constants.TAG + ": PassphraseCacheService"; @@ -74,9 +80,9 @@ public class PassphraseCacheService extends Service { Context mContext; /** - * This caches a new passphrase by sending a new command to the service. An android service is - * only run once. Thus, when the service is already started, new commands just add new events to - * the alarm manager for new passphrases to let them timeout in the future. + * This caches a new passphrase in memory by sending a new command to the service. An android + * service is only run once. Thus, when the service is already started, new commands just add + * new events to the alarm manager for new passphrases to let them timeout in the future. * * @param context * @param keyId @@ -95,21 +101,23 @@ public class PassphraseCacheService extends Service { } /** - * Gets a cached passphrase from memory, blocking method + * Gets a cached passphrase from memory by sending an intent to the service. This method is + * designed to wait until the service returns the passphrase. * * @param context * @param keyId - * @return + * @return passphrase or null (if no passphrase is cached for this keyId) */ public static String getCachedPassphrase(Context context, long keyId) { Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId); + Intent intent = new Intent(context, PassphraseCacheService.class); intent.setAction(ACTION_PASSPHRASE_CACHE_GET); final Object mutex = new Object(); final Bundle returnBundle = new Bundle(); - HandlerThread handlerThread = new HandlerThread("getPassphrase"); + HandlerThread handlerThread = new HandlerThread("getPassphraseThread"); handlerThread.start(); Handler returnHandler = new Handler(handlerThread.getLooper()) { @Override @@ -121,6 +129,7 @@ public class PassphraseCacheService extends Service { synchronized (mutex) { mutex.notify(); } + // quit handlerThread getLooper().quit(); } }; @@ -147,6 +156,12 @@ public class PassphraseCacheService extends Service { } } + /** + * Internal implementation to get cached passphrase. + * + * @param keyId + * @return + */ private String getCachedPassphraseImpl(long keyId) { Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId); @@ -168,15 +183,15 @@ public class PassphraseCacheService extends Service { // get cached passphrase String cachedPassphrase = mPassphraseCache.get(masterKeyId); if (cachedPassphrase == null) { - // TODO: fix! - // check if secret key has a passphrase - // if (!hasPassphrase(context, masterKeyId)) { - // // cache empty passphrase - // addCachedPassphrase(context, masterKeyId, ""); - // return ""; - // } else { - return null; - // } + // if key has no passphrase -> cache and return empty passphrase + if (!hasPassphrase(this, masterKeyId)) { + Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!"); + + addCachedPassphrase(this, masterKeyId, ""); + return ""; + } else { + return null; + } } // set it again to reset the cache life cycle Log.d(TAG, "Cache passphrase again when getting it!"); @@ -196,17 +211,10 @@ public class PassphraseCacheService extends Service { try { PGPSecretKey secretKey = PgpHelper.getMasterKey(ProviderHelper .getPGPSecretKeyRingByKeyId(context, secretKeyId)); - - Log.d(Constants.TAG, "Check if key has no passphrase..."); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( "SC").build("".toCharArray()); PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); if (testKey != null) { - Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!"); - - // cache empty passphrase - PassphraseCacheService.addCachedPassphrase(context, secretKey.getKeyID(), ""); - return false; } } catch (PGPException e) { -- cgit v1.2.3 From f6fc6caa1c112ae79ec2fc436a7db2f81a12c6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 29 May 2013 15:58:50 +0200 Subject: rename to openintents namespace --- .../keychain/crypto_provider/CryptoService.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index 1a57a457d..a367c613f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -20,6 +20,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; + +import org.openintents.crypto.CryptoError; +import org.openintents.crypto.CryptoSignatureResult; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.helper.PgpMain; @@ -29,10 +32,8 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import com.android.crypto.CryptoError; -import com.android.crypto.ICryptoCallback; -import com.android.crypto.ICryptoService; -import com.android.crypto.CryptoSignatureResult; +import org.openintents.crypto.ICryptoCallback; +import org.openintents.crypto.ICryptoService; import android.app.Service; import android.content.Context; @@ -89,7 +90,8 @@ public class CryptoService extends Service { // passphrase! Intent intent = new Intent(CryptoActivity.ACTION_CACHE_PASSPHRASE); intent.putExtra(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - callback.onActivityRequired(intent); + // TODO: start activity bind to service from activity send back intent on success +// callback.onActivityRequired(intent); return; } -- cgit v1.2.3 From 41338e115cb015c492dc44f224bc4b4cffe15cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 17 Jun 2013 15:52:09 +0200 Subject: Better API demo, open activity from service, discover crypto provider with packagemanager instead of register intent --- .../keychain/crypto_provider/CryptoActivity.java | 119 +++++++++++++- .../keychain/crypto_provider/CryptoService.java | 180 ++++++++++++++++----- .../crypto_provider/ICryptoServiceActivity.aidl | 28 ++++ .../keychain/crypto_provider/RegisterActivity.java | 74 --------- .../keychain/util/PausableThreadPoolExecutor.java | 89 ++++++++++ 5 files changed, 372 insertions(+), 118 deletions(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java index b1d248e42..7ffc42022 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java @@ -1,19 +1,36 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.sufficientlysecure.keychain.crypto_provider; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; import com.actionbarsherlock.app.SherlockFragmentActivity; -import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.view.View; @@ -22,21 +39,81 @@ import android.widget.Button; public class CryptoActivity extends SherlockFragmentActivity { + public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; - public static final String EXTRA_SECRET_KEY_ID = "secret_key_id"; + public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; + public static final String EXTRA_PACKAGE_NAME = "packageName"; + + private ICryptoServiceActivity mService; + private boolean mServiceBound; + + private ServiceConnection mServiceActivityConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = ICryptoServiceActivity.Stub.asInterface(service); + Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); + mServiceBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); + mServiceBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mServiceBound) { // if not already connected + try { + Log.d(Constants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction("org.openintents.crypto.ICryptoService"); + bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(Constants.TAG, "Exception", e); + return false; + } + } else { // already connected + Log.d(Constants.TAG, "already bound... "); + return true; + } + } + + public void unbindFromService() { + unbindService(mServiceActivityConnection); + } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Log.d(Constants.TAG, "onCreate…"); + + // bind to our own crypto service + bindToService(); + handleActions(getIntent()); } - protected void handleActions(Intent intent) { + @Override + protected void onDestroy() { + super.onDestroy(); - // TODO: Important: Check if calling package is in list! + // unbind from our crypto service + if (mServiceActivityConnection != null) { + unbindFromService(); + } + } + protected void handleActions(Intent intent) { String action = intent.getAction(); Bundle extras = intent.getExtras(); @@ -47,7 +124,35 @@ public class CryptoActivity extends SherlockFragmentActivity { /** * com.android.crypto actions */ - if (ACTION_CACHE_PASSPHRASE.equals(action)) { + if (ACTION_REGISTER.equals(action)) { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + + setContentView(R.layout.register_crypto_consumer_activity); + + Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); + Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); + + allowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName); + // Intent data = new Intent(); + + setResult(RESULT_OK); + finish(); + } + }); + + disallowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }); + } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); showPassphraseDialog(secretKeyId); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index a367c613f..10eb94c7f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -20,6 +20,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; import org.openintents.crypto.CryptoError; import org.openintents.crypto.CryptoSignatureResult; @@ -29,8 +32,10 @@ import org.sufficientlysecure.keychain.helper.PgpMain; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor; import org.openintents.crypto.ICryptoCallback; import org.openintents.crypto.ICryptoService; @@ -38,6 +43,7 @@ import org.openintents.crypto.ICryptoService; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -45,11 +51,26 @@ import android.os.RemoteException; public class CryptoService extends Service { Context mContext; + // just one pool of 4 threads, pause on every user action needed + final ArrayBlockingQueue mPoolQueue = new ArrayBlockingQueue(20); + PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10, + TimeUnit.SECONDS, mPoolQueue); + + private ArrayList mAllowedPackages; + + // RemoteCallbackList + + public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.ICryptoServiceActivity"; + @Override public void onCreate() { super.onCreate(); mContext = this; Log.d(Constants.TAG, "CryptoService, onCreate()"); + + // load allowed packages from database + mAllowedPackages = ProviderHelper.getCryptoConsumers(mContext); + Log.d(Constants.TAG, "allowed: " + mAllowedPackages); } @Override @@ -60,7 +81,20 @@ public class CryptoService extends Service { @Override public IBinder onBind(Intent intent) { - return mBinder; + // return different binder for connections from internal service activity + if (ACTION_SERVICE_ACTIVITY.equals(intent.getAction())) { + String callingPackageName = intent.getPackage(); + + // this binder can only be used from OpenPGP Keychain + if (callingPackageName.equals(Constants.PACKAGE_NAME)) { + return mBinderServiceActivity; + } else { + Log.e(Constants.TAG, "This binder can only be used from " + Constants.PACKAGE_NAME); + return null; + } + } else { + return mBinder; + } } private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) @@ -77,8 +111,8 @@ public class CryptoService extends Service { if (secretKeyId == Id.key.none) { throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound)); } - - Log.d(Constants.TAG, "Got input:\n"+new String(inputBytes)); + + Log.d(Constants.TAG, "Got input:\n" + new String(inputBytes)); Log.d(Constants.TAG, "secretKeyId " + secretKeyId); @@ -86,13 +120,11 @@ public class CryptoService extends Service { if (passphrase == null) { Log.d(Constants.TAG, "No passphrase! Activity required!"); - // No passphrase cached for this ciphertext! Intent required to cache - // passphrase! - Intent intent = new Intent(CryptoActivity.ACTION_CACHE_PASSPHRASE); - intent.putExtra(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - // TODO: start activity bind to service from activity send back intent on success -// callback.onActivityRequired(intent); - return; + + // start passphrase dialog + Bundle extras = new Bundle(); + extras.putLong(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); + pauseQueueAndStartCryptoActivity(CryptoActivity.ACTION_CACHE_PASSPHRASE, extras); } // if (signedOnly) { @@ -162,37 +194,111 @@ public class CryptoService extends Service { } @Override - public void decryptAndVerify(byte[] inputBytes, ICryptoCallback callback) + public void decryptAndVerify(final byte[] inputBytes, final ICryptoCallback callback) throws RemoteException { - decryptAndVerifySafe(inputBytes, callback); + + Runnable r = new Runnable() { + + @Override + public void run() { + try { + decryptAndVerifySafe(inputBytes, callback); + } catch (RemoteException e) { + Log.e(Constants.TAG, "CryptoService", e); + } + } + }; + + checkAndEnqueue(r); } }; - // /** - // * As we can not throw an exception through Android RPC, we assign identifiers to the - // exception - // * types. - // * - // * @param e - // * @return - // */ - // private int getExceptionId(Exception e) { - // if (e instanceof NoSuchProviderException) { - // return 0; - // } else if (e instanceof NoSuchAlgorithmException) { - // return 1; - // } else if (e instanceof SignatureException) { - // return 2; - // } else if (e instanceof IOException) { - // return 3; - // } else if (e instanceof PgpGeneralException) { - // return 4; - // } else if (e instanceof PGPException) { - // return 5; - // } else { - // return -1; - // } - // } + private final ICryptoServiceActivity.Stub mBinderServiceActivity = new ICryptoServiceActivity.Stub() { + + @Override + public void register(boolean success, String packageName) throws RemoteException { + if (success) { + // reload allowed packages + mAllowedPackages = ProviderHelper.getCryptoConsumers(mContext); + + // resume threads + if (isCallerAllowed()) { + mThreadPool.resume(); + } else { + // TODO: should not happen? + } + } else { + // TODO + mPoolQueue.clear(); + } + + } + + @Override + public void cachePassphrase(boolean success, String passphrase) throws RemoteException { + + } + + }; + + private void checkAndEnqueue(Runnable r) { + if (isCallerAllowed()) { + mThreadPool.execute(r); + + Log.d(Constants.TAG, "Enqueued runnable…"); + } else { + Log.e(Constants.TAG, "Not allowed to use service! Starting register with activity!"); + pauseQueueAndStartCryptoActivity(CryptoActivity.ACTION_REGISTER, null); + mThreadPool.execute(r); + + Log.d(Constants.TAG, "Enqueued runnable…"); + } + } + + /** + * Checks if process that binds to this service (i.e. the package name corresponding to the + * process) is in the list of allowed package names. + * + * @return true if process is allowed to use this service + */ + private boolean isCallerAllowed() { + String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); + + // is calling package allowed to use this service? + for (int i = 0; i < callingPackages.length; i++) { + String currentPkg = callingPackages[i]; + Log.d(Constants.TAG, "Caller packageName: " + currentPkg); + + // check if package is allowed to use our service + if (mAllowedPackages.contains(currentPkg)) { + Log.d(Constants.TAG, "Caller is allowed! packageName: " + currentPkg); + + return true; + } else if (Constants.PACKAGE_NAME.equals(currentPkg)) { + Log.d(Constants.TAG, "Caller is OpenPGP Keychain! -> allowed!"); + + return true; + } + } + + Log.d(Constants.TAG, "Caller is NOT allowed!"); + return false; + } + + private void pauseQueueAndStartCryptoActivity(String action, Bundle extras) { + mThreadPool.pause(); + + Log.d(Constants.TAG, "starting activity..."); + Intent intent = new Intent(getBaseContext(), CryptoActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + intent.setAction(action); + if (extras != null) { + intent.putExtras(extras); + } + getApplication().startActivity(intent); + } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl new file mode 100644 index 000000000..51586cae6 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.crypto_provider; + + +interface ICryptoServiceActivity { + + + oneway void register(in boolean success, in String packageName); + + oneway void cachePassphrase(in boolean success, in String passphrase); + + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java deleted file mode 100644 index 39b29f9a0..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.sufficientlysecure.keychain.crypto_provider; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.util.Log; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class RegisterActivity extends Activity { - - public static final String ACTION_REGISTER = "com.android.crypto.REGISTER"; - - public static final String EXTRA_PACKAGE_NAME = "packageName"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - handleActions(getIntent()); - } - - protected void handleActions(Intent intent) { - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - final String callingPackageName = this.getCallingPackage(); - - /** - * com.android.crypto actions - */ - if (ACTION_REGISTER.equals(action)) { - setContentView(R.layout.register_crypto_consumer_activity); - - Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); - Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); - - allowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName); - Intent data = new Intent(); - data.putExtra(EXTRA_PACKAGE_NAME, "org.sufficientlysecure.keychain"); - - setResult(RESULT_OK, data); - finish(); - } - }); - - disallowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }); - - } else { - Log.e(Constants.TAG, "Please use com.android.crypto.REGISTER as intent action!"); - finish(); - } - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java new file mode 100644 index 000000000..d6170a4e2 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/PausableThreadPoolExecutor.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.util; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Example from + * http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html + */ +public class PausableThreadPoolExecutor extends ThreadPoolExecutor { + + public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, + TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); + } + + public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, + TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); + } + + public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, + TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); + } + + public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, + TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + private boolean isPaused; + private ReentrantLock pauseLock = new ReentrantLock(); + private Condition unpaused = pauseLock.newCondition(); + + protected void beforeExecute(Thread t, Runnable r) { + super.beforeExecute(t, r); + pauseLock.lock(); + try { + while (isPaused) + unpaused.await(); + } catch (InterruptedException ie) { + t.interrupt(); + } finally { + pauseLock.unlock(); + } + } + + public void pause() { + pauseLock.lock(); + try { + isPaused = true; + } finally { + pauseLock.unlock(); + } + } + + public void resume() { + pauseLock.lock(); + try { + isPaused = false; + unpaused.signalAll(); + } finally { + pauseLock.unlock(); + } + } +} \ No newline at end of file -- cgit v1.2.3 From 918bab3a4e7b582dce5b994e115ca8de37da4ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 17 Jun 2013 16:05:39 +0200 Subject: Rename foir clarification --- .../keychain/crypto_provider/CryptoActivity.java | 197 --------------------- .../keychain/crypto_provider/CryptoService.java | 14 +- .../crypto_provider/ICryptoServiceActivity.aidl | 28 --- .../crypto_provider/IServiceActivityCallback.aidl | 28 +++ .../keychain/crypto_provider/ServiceActivity.java | 197 +++++++++++++++++++++ 5 files changed, 232 insertions(+), 232 deletions(-) delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java deleted file mode 100644 index 7ffc42022..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.crypto_provider; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import com.actionbarsherlock.app.SherlockFragmentActivity; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class CryptoActivity extends SherlockFragmentActivity { - - public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; - public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; - - public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; - public static final String EXTRA_PACKAGE_NAME = "packageName"; - - private ICryptoServiceActivity mService; - private boolean mServiceBound; - - private ServiceConnection mServiceActivityConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - mService = ICryptoServiceActivity.Stub.asInterface(service); - Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); - mServiceBound = true; - } - - public void onServiceDisconnected(ComponentName name) { - mService = null; - Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); - mServiceBound = false; - } - }; - - /** - * If not already bound, bind! - * - * @return - */ - public boolean bindToService() { - if (mService == null && !mServiceBound) { // if not already connected - try { - Log.d(Constants.TAG, "not bound yet"); - - Intent serviceIntent = new Intent(); - serviceIntent.setAction("org.openintents.crypto.ICryptoService"); - bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); - - return true; - } catch (Exception e) { - Log.d(Constants.TAG, "Exception", e); - return false; - } - } else { // already connected - Log.d(Constants.TAG, "already bound... "); - return true; - } - } - - public void unbindFromService() { - unbindService(mServiceActivityConnection); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d(Constants.TAG, "onCreate…"); - - // bind to our own crypto service - bindToService(); - - handleActions(getIntent()); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - // unbind from our crypto service - if (mServiceActivityConnection != null) { - unbindFromService(); - } - } - - protected void handleActions(Intent intent) { - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - /** - * com.android.crypto actions - */ - if (ACTION_REGISTER.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - - setContentView(R.layout.register_crypto_consumer_activity); - - Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); - Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); - - allowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - // ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName); - // Intent data = new Intent(); - - setResult(RESULT_OK); - finish(); - } - }); - - disallowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }); - } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { - long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); - - showPassphraseDialog(secretKeyId); - } else { - Log.e(Constants.TAG, "Wrong action!"); - setResult(RESULT_CANCELED); - finish(); - } - } - - /** - * Shows passphrase dialog to cache a new passphrase the user enters for using it later for - * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks - * for a symmetric passphrase - */ - private void showPassphraseDialog(long secretKeyId) { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - setResult(RESULT_OK); - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - try { - PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, - messenger, secretKeyId); - - passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PgpMain.PgpGeneralException e) { - Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); - // send message to handler to start encryption directly - returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); - } - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index 10eb94c7f..3748ef521 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -60,7 +60,7 @@ public class CryptoService extends Service { // RemoteCallbackList - public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.ICryptoServiceActivity"; + public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"; @Override public void onCreate() { @@ -123,8 +123,8 @@ public class CryptoService extends Service { // start passphrase dialog Bundle extras = new Bundle(); - extras.putLong(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - pauseQueueAndStartCryptoActivity(CryptoActivity.ACTION_CACHE_PASSPHRASE, extras); + extras.putLong(ServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); + pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_CACHE_PASSPHRASE, extras); } // if (signedOnly) { @@ -214,7 +214,7 @@ public class CryptoService extends Service { }; - private final ICryptoServiceActivity.Stub mBinderServiceActivity = new ICryptoServiceActivity.Stub() { + private final IServiceActivityCallback.Stub mBinderServiceActivity = new IServiceActivityCallback.Stub() { @Override public void register(boolean success, String packageName) throws RemoteException { @@ -249,7 +249,7 @@ public class CryptoService extends Service { Log.d(Constants.TAG, "Enqueued runnable…"); } else { Log.e(Constants.TAG, "Not allowed to use service! Starting register with activity!"); - pauseQueueAndStartCryptoActivity(CryptoActivity.ACTION_REGISTER, null); + pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, null); mThreadPool.execute(r); Log.d(Constants.TAG, "Enqueued runnable…"); @@ -286,11 +286,11 @@ public class CryptoService extends Service { return false; } - private void pauseQueueAndStartCryptoActivity(String action, Bundle extras) { + private void pauseQueueAndStartServiceActivity(String action, Bundle extras) { mThreadPool.pause(); Log.d(Constants.TAG, "starting activity..."); - Intent intent = new Intent(getBaseContext(), CryptoActivity.class); + Intent intent = new Intent(getBaseContext(), ServiceActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl deleted file mode 100644 index 51586cae6..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ICryptoServiceActivity.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.crypto_provider; - - -interface ICryptoServiceActivity { - - - oneway void register(in boolean success, in String packageName); - - oneway void cachePassphrase(in boolean success, in String passphrase); - - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl new file mode 100644 index 000000000..61a8da06c --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.crypto_provider; + + +interface IServiceActivityCallback { + + + oneway void register(in boolean success, in String packageName); + + oneway void cachePassphrase(in boolean success, in String passphrase); + + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java new file mode 100644 index 000000000..9f68aab97 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.crypto_provider; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.PgpMain; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Log; + +import com.actionbarsherlock.app.SherlockFragmentActivity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class ServiceActivity extends SherlockFragmentActivity { + + public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; + public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; + + public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; + public static final String EXTRA_PACKAGE_NAME = "packageName"; + + private IServiceActivityCallback mService; + private boolean mServiceBound; + + private ServiceConnection mServiceActivityConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = IServiceActivityCallback.Stub.asInterface(service); + Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); + mServiceBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); + mServiceBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mServiceBound) { // if not already connected + try { + Log.d(Constants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction("org.openintents.crypto.ICryptoService"); + bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(Constants.TAG, "Exception", e); + return false; + } + } else { // already connected + Log.d(Constants.TAG, "already bound... "); + return true; + } + } + + public void unbindFromService() { + unbindService(mServiceActivityConnection); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.d(Constants.TAG, "onCreate…"); + + // bind to our own crypto service + bindToService(); + + handleActions(getIntent()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // unbind from our crypto service + if (mServiceActivityConnection != null) { + unbindFromService(); + } + } + + protected void handleActions(Intent intent) { + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + /** + * com.android.crypto actions + */ + if (ACTION_REGISTER.equals(action)) { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + + setContentView(R.layout.register_crypto_consumer_activity); + + Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); + Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); + + allowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName); + // Intent data = new Intent(); + + setResult(RESULT_OK); + finish(); + } + }); + + disallowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }); + } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { + long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); + + showPassphraseDialog(secretKeyId); + } else { + Log.e(Constants.TAG, "Wrong action!"); + setResult(RESULT_CANCELED); + finish(); + } + } + + /** + * Shows passphrase dialog to cache a new passphrase the user enters for using it later for + * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks + * for a symmetric passphrase + */ + private void showPassphraseDialog(long secretKeyId) { + // Message is received after passphrase is cached + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + setResult(RESULT_OK); + finish(); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + try { + PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, + messenger, secretKeyId); + + passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); + } catch (PgpMain.PgpGeneralException e) { + Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); + // send message to handler to start encryption directly + returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); + } + } +} -- cgit v1.2.3 From 0f3e78ebf7d0c71a18fef55e543c5b54a066735b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 17 Jun 2013 16:59:27 +0200 Subject: Possible to add allowed packages --- .../keychain/crypto_provider/CryptoService.java | 45 ++++++++++++++-------- .../keychain/crypto_provider/ServiceActivity.java | 3 +- .../keychain/provider/KeychainContract.java | 4 ++ .../keychain/provider/KeychainProvider.java | 9 ++++- 4 files changed, 43 insertions(+), 18 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index 3748ef521..a70641b58 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -58,8 +58,6 @@ public class CryptoService extends Service { private ArrayList mAllowedPackages; - // RemoteCallbackList - public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"; @Override @@ -218,12 +216,13 @@ public class CryptoService extends Service { @Override public void register(boolean success, String packageName) throws RemoteException { + if (success) { // reload allowed packages mAllowedPackages = ProviderHelper.getCryptoConsumers(mContext); // resume threads - if (isCallerAllowed()) { + if (isPackageAllowed(packageName)) { mThreadPool.resume(); } else { // TODO: should not happen? @@ -248,8 +247,15 @@ public class CryptoService extends Service { Log.d(Constants.TAG, "Enqueued runnable…"); } else { - Log.e(Constants.TAG, "Not allowed to use service! Starting register with activity!"); - pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, null); + String[] callingPackages = getPackageManager() + .getPackagesForUid(Binder.getCallingUid()); + + Log.e(Constants.TAG, "Not allowed to use service! Starting activity for registration!"); + Bundle extras = new Bundle(); + // TODO: currently simply uses first entry + extras.putString(ServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]); + pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, extras); + mThreadPool.execute(r); Log.d(Constants.TAG, "Enqueued runnable…"); @@ -268,24 +274,33 @@ public class CryptoService extends Service { // is calling package allowed to use this service? for (int i = 0; i < callingPackages.length; i++) { String currentPkg = callingPackages[i]; - Log.d(Constants.TAG, "Caller packageName: " + currentPkg); - - // check if package is allowed to use our service - if (mAllowedPackages.contains(currentPkg)) { - Log.d(Constants.TAG, "Caller is allowed! packageName: " + currentPkg); - - return true; - } else if (Constants.PACKAGE_NAME.equals(currentPkg)) { - Log.d(Constants.TAG, "Caller is OpenPGP Keychain! -> allowed!"); + if (isPackageAllowed(currentPkg)) { return true; } } - + Log.d(Constants.TAG, "Caller is NOT allowed!"); return false; } + private boolean isPackageAllowed(String packageName) { + Log.d(Constants.TAG, "packageName: " + packageName); + + // check if package is allowed to use our service + if (mAllowedPackages.contains(packageName)) { + Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + + return true; + } else if (Constants.PACKAGE_NAME.equals(packageName)) { + Log.d(Constants.TAG, "Package is OpenPGP Keychain! -> allowed!"); + + return true; + } + + return false; + } + private void pauseQueueAndStartServiceActivity(String action, Bundle extras) { mThreadPool.pause(); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java index 9f68aab97..7efce85c7 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.crypto_provider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.PgpMain; +import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -136,7 +137,7 @@ public class ServiceActivity extends SherlockFragmentActivity { @Override public void onClick(View v) { - // ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName); + ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); // Intent data = new Intent(); setResult(RESULT_OK); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java index 46928c6fa..776d1bfb9 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -222,6 +222,10 @@ public class KeychainContract { /** Use if a single item is returned */ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.crypto_consumers"; + + public static Uri buildIdUri(String rowId) { + return CONTENT_URI.buildUpon().appendPath(rowId).build(); + } } public static class DataStream { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 49286b9ce..70be38e21 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -600,10 +600,10 @@ public class KeychainProvider extends ContentProvider { qb.appendWhereEscapeString(uri.getLastPathSegment()); break; - + case CRYPTO_CONSUMERS: qb.setTables(Tables.CRYPTO_CONSUMERS); - + break; default: @@ -685,6 +685,11 @@ public class KeychainProvider extends ContentProvider { rowId = db.insertOrThrow(Tables.USER_IDS, null, values); rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId)); + break; + case CRYPTO_CONSUMERS: + rowId = db.insertOrThrow(Tables.CRYPTO_CONSUMERS, null, values); + rowUri = CryptoConsumers.buildIdUri(Long.toString(rowId)); + break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); -- cgit v1.2.3 From d4e054d5f24afeef8859c9294f3ef1b69242b037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 17 Jun 2013 19:51:41 +0200 Subject: some fixes all over --- .../keychain/crypto_provider/CryptoService.java | 66 +++++++++++++++++----- .../keychain/provider/KeychainProvider.java | 49 +++++++++++++--- 2 files changed, 95 insertions(+), 20 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index a70641b58..7ff8c0e3e 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -56,8 +56,6 @@ public class CryptoService extends Service { PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, mPoolQueue); - private ArrayList mAllowedPackages; - public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"; @Override @@ -65,10 +63,6 @@ public class CryptoService extends Service { super.onCreate(); mContext = this; Log.d(Constants.TAG, "CryptoService, onCreate()"); - - // load allowed packages from database - mAllowedPackages = ProviderHelper.getCryptoConsumers(mContext); - Log.d(Constants.TAG, "allowed: " + mAllowedPackages); } @Override @@ -95,6 +89,40 @@ public class CryptoService extends Service { } } + private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds, + ICryptoCallback callback) throws RemoteException { + try { + // build InputData and write into OutputStream + InputStream inputStream = new ByteArrayInputStream(inputBytes); + long inputLength = inputBytes.length; + InputData inputData = new InputData(inputStream, inputLength); + + OutputStream outStream = new ByteArrayOutputStream(); + + // TODO: hardcoded... + boolean useAsciiArmor = true; + int compressionId = 2; // zlib + + // PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor, + // compressionId, encryptionKeyIds, encryptionPassphrase, Preferences + // .getPreferences(this).getDefaultEncryptionAlgorithm(), + // secretKeyId, + // Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences + // .getPreferences(this).getForceV3Signatures(), + // PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); + + outStream.close(); + } catch (Exception e) { + Log.e(Constants.TAG, "KeychainService, Exception!", e); + + try { + callback.onError(new CryptoError(0, e.getMessage())); + } catch (Exception t) { + Log.e(Constants.TAG, "Error returning exception to client", t); + } + } + } + private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) throws RemoteException { try { @@ -171,10 +199,22 @@ public class CryptoService extends Service { private final ICryptoService.Stub mBinder = new ICryptoService.Stub() { @Override - public void encrypt(byte[] inputBytes, String[] encryptionUserIds, ICryptoCallback callback) - throws RemoteException { - // TODO Auto-generated method stub + public void encrypt(final byte[] inputBytes, final String[] encryptionUserIds, + final ICryptoCallback callback) throws RemoteException { + Runnable r = new Runnable() { + + @Override + public void run() { + try { + encryptSafe(inputBytes, encryptionUserIds, callback); + } catch (RemoteException e) { + Log.e(Constants.TAG, "CryptoService", e); + } + } + }; + + checkAndEnqueue(r); } @Override @@ -218,9 +258,6 @@ public class CryptoService extends Service { public void register(boolean success, String packageName) throws RemoteException { if (success) { - // reload allowed packages - mAllowedPackages = ProviderHelper.getCryptoConsumers(mContext); - // resume threads if (isPackageAllowed(packageName)) { mThreadPool.resume(); @@ -287,8 +324,11 @@ public class CryptoService extends Service { private boolean isPackageAllowed(String packageName) { Log.d(Constants.TAG, "packageName: " + packageName); + ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(mContext); + Log.d(Constants.TAG, "allowed: " + allowedPkgs); + // check if package is allowed to use our service - if (mAllowedPackages.contains(packageName)) { + if (allowedPkgs.contains(packageName)) { Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); return true; diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 70be38e21..a34cda0c3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2012-2013 Dominik Schürmann * Copyright (C) 2010 Thialfihar * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,8 +17,6 @@ package org.sufficientlysecure.keychain.provider; -import java.io.File; -import java.io.FileNotFoundException; import java.util.Arrays; import java.util.HashMap; @@ -44,7 +42,6 @@ import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; -import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.text.TextUtils; @@ -82,6 +79,7 @@ public class KeychainProvider extends ContentProvider { private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222; private static final int CRYPTO_CONSUMERS = 301; + private static final int CRYPTO_CONSUMERS_BY_ROW_ID = 302; // private static final int DATA_STREAM = 401; @@ -230,6 +228,8 @@ public class KeychainProvider extends ContentProvider { * Crypto Consumers */ matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS, CRYPTO_CONSUMERS); + matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS + "/#", + CRYPTO_CONSUMERS_BY_ROW_ID); /** * data stream @@ -293,6 +293,9 @@ public class KeychainProvider extends ContentProvider { case CRYPTO_CONSUMERS: return CryptoConsumers.CONTENT_TYPE; + case CRYPTO_CONSUMERS_BY_ROW_ID: + return CryptoConsumers.CONTENT_ITEM_TYPE; + default: throw new UnsupportedOperationException("Unknown uri: " + uri); } @@ -653,6 +656,7 @@ public class KeychainProvider extends ContentProvider { rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); rowUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case PUBLIC_KEY_RING_KEY: @@ -660,11 +664,13 @@ public class KeychainProvider extends ContentProvider { rowId = db.insertOrThrow(Tables.KEYS, null, values); rowUri = Keys.buildPublicKeysUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case PUBLIC_KEY_RING_USER_ID: rowId = db.insertOrThrow(Tables.USER_IDS, null, values); rowUri = UserIds.buildPublicUserIdsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case SECRET_KEY_RING: @@ -672,6 +678,7 @@ public class KeychainProvider extends ContentProvider { rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); rowUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case SECRET_KEY_RING_KEY: @@ -679,6 +686,7 @@ public class KeychainProvider extends ContentProvider { rowId = db.insertOrThrow(Tables.KEYS, null, values); rowUri = Keys.buildSecretKeysUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case SECRET_KEY_RING_USER_ID: @@ -697,7 +705,6 @@ public class KeychainProvider extends ContentProvider { // notify of changes in db getContext().getContentResolver().notifyChange(uri, null); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); } catch (SQLiteConstraintException e) { Log.e(Constants.TAG, "Constraint exception on insert! Entry already existing?"); @@ -725,6 +732,7 @@ public class KeychainProvider extends ContentProvider { count = db.delete(Tables.KEY_RINGS, buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: case SECRET_KEY_RING_BY_MASTER_KEY_ID: @@ -733,24 +741,29 @@ public class KeychainProvider extends ContentProvider { count = db.delete(Tables.KEY_RINGS, buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case PUBLIC_KEY_RING_KEY_BY_ROW_ID: case SECRET_KEY_RING_KEY_BY_ROW_ID: count = db.delete(Tables.KEYS, buildDefaultKeysSelection(uri, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); break; case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: case SECRET_KEY_RING_USER_ID_BY_ROW_ID: count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection), selectionArgs); break; + case CRYPTO_CONSUMERS_BY_ROW_ID: + count = db.delete(Tables.CRYPTO_CONSUMERS, + buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); + break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); } // notify of changes in db getContext().getContentResolver().notifyChange(uri, null); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); return count; } @@ -776,6 +789,8 @@ public class KeychainProvider extends ContentProvider { values, buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + break; case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: case SECRET_KEY_RING_BY_MASTER_KEY_ID: @@ -786,6 +801,8 @@ public class KeychainProvider extends ContentProvider { values, buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + break; case PUBLIC_KEY_RING_KEY_BY_ROW_ID: case SECRET_KEY_RING_KEY_BY_ROW_ID: @@ -793,6 +810,8 @@ public class KeychainProvider extends ContentProvider { .update(Tables.KEYS, values, buildDefaultKeysSelection(uri, getKeyType(match), selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + break; case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: case SECRET_KEY_RING_USER_ID_BY_ROW_ID: @@ -805,7 +824,6 @@ public class KeychainProvider extends ContentProvider { // notify of changes in db getContext().getContentResolver().notifyChange(uri, null); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); } catch (SQLiteConstraintException e) { Log.e(Constants.TAG, "Constraint exception on update! Entry already existing?"); @@ -888,6 +906,23 @@ public class KeychainProvider extends ContentProvider { return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andSelection; } + /** + * Build default selection statement for Crypto Consumers. If no extra selection is specified + * only build where clause with rowId + * + * @param uri + * @param selection + * @return + */ + private String buildDefaultCryptoConsumersSelection(Uri uri, String selection) { + String andSelection = ""; + if (!TextUtils.isEmpty(selection)) { + andSelection = " AND (" + selection + ")"; + } + + return selection + andSelection; + } + // @Override // public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { // int match = mUriMatcher.match(uri); -- cgit v1.2.3 From 36cc814e84135296fc14d383e61e6b4fe8dfe269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 18 Jun 2013 01:48:25 +0200 Subject: Add database columns for crypto consumer preferences --- .../keychain/provider/KeychainContract.java | 13 ++++++++++++- .../keychain/provider/KeychainDatabase.java | 6 +++++- .../keychain/provider/KeychainProvider.java | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java index 776d1bfb9..985498e3a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -43,7 +43,7 @@ public class KeychainContract { String CREATION = "creation"; String EXPIRY = "expiry"; String KEY_RING_ROW_ID = "key_ring_row_id"; // foreign key to key_rings._ID - String KEY_DATA = "key_data"; // PGPPublicKey / PGPSecretKey blob + String KEY_DATA = "key_data"; // PGPPublicKey/PGPSecretKey blob String RANK = "rank"; } @@ -55,6 +55,11 @@ public class KeychainContract { interface CryptoConsumersColumns { String PACKAGE_NAME = "package_name"; + String PRIVATE_KEY_ID = "private_key_id"; // not a database id + String ASCII_ARMOR = "ascii_armor"; + String ENCRYPTION_ALGORITHM = "encryption_algorithm"; + String HASH_ALORITHM = "hash_algorithm"; + String COMPRESSION = "compression"; } public static final class KeyTypes { @@ -83,6 +88,7 @@ public class KeychainContract { public static final String PATH_KEYS = "keys"; public static final String BASE_CRYPTO_CONSUMERS = "crypto_consumers"; + public static final String PATH_BY_PACKAGE_NAME = "package_name"; public static class KeyRings implements KeyRingsColumns, BaseColumns { public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() @@ -226,6 +232,11 @@ public class KeychainContract { public static Uri buildIdUri(String rowId) { return CONTENT_URI.buildUpon().appendPath(rowId).build(); } + + public static Uri buildByPackageNameUri(String packageName) { + return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName) + .build(); + } } public static class DataStream { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index f30292b52..6f31f4945 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -67,7 +67,11 @@ public class KeychainDatabase extends SQLiteOpenHelper { private static final String CREATE_CRYPTO_CONSUMERS = "CREATE TABLE IF NOT EXISTS " + Tables.CRYPTO_CONSUMERS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + CryptoConsumersColumns.PACKAGE_NAME - + " TEXT UNIQUE)"; + + " TEXT UNIQUE, " + CryptoConsumersColumns.PRIVATE_KEY_ID + " INT64, " + + CryptoConsumersColumns.ASCII_ARMOR + " INTEGER, " + + CryptoConsumersColumns.ENCRYPTION_ALGORITHM + " INTEGER, " + + CryptoConsumersColumns.HASH_ALORITHM + " INTEGER, " + + CryptoConsumersColumns.COMPRESSION + " INTEGER)"; KeychainDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index a34cda0c3..5a86b0bdb 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -80,6 +80,7 @@ public class KeychainProvider extends ContentProvider { private static final int CRYPTO_CONSUMERS = 301; private static final int CRYPTO_CONSUMERS_BY_ROW_ID = 302; + private static final int CRYPTO_CONSUMERS_BY_PACKAGE_NAME = 303; // private static final int DATA_STREAM = 401; @@ -230,6 +231,8 @@ public class KeychainProvider extends ContentProvider { matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS, CRYPTO_CONSUMERS); matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS + "/#", CRYPTO_CONSUMERS_BY_ROW_ID); + matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS + "/" + + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", CRYPTO_CONSUMERS_BY_PACKAGE_NAME); /** * data stream @@ -294,6 +297,7 @@ public class KeychainProvider extends ContentProvider { return CryptoConsumers.CONTENT_TYPE; case CRYPTO_CONSUMERS_BY_ROW_ID: + case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: return CryptoConsumers.CONTENT_ITEM_TYPE; default: @@ -607,6 +611,12 @@ public class KeychainProvider extends ContentProvider { case CRYPTO_CONSUMERS: qb.setTables(Tables.CRYPTO_CONSUMERS); + break; + case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: + qb.setTables(Tables.CRYPTO_CONSUMERS); + qb.appendWhere(CryptoConsumers.PACKAGE_NAME + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + break; default: @@ -755,6 +765,7 @@ public class KeychainProvider extends ContentProvider { selectionArgs); break; case CRYPTO_CONSUMERS_BY_ROW_ID: + case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: count = db.delete(Tables.CRYPTO_CONSUMERS, buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); break; @@ -818,6 +829,11 @@ public class KeychainProvider extends ContentProvider { count = db.update(Tables.USER_IDS, values, buildDefaultUserIdsSelection(uri, selection), selectionArgs); break; + case CRYPTO_CONSUMERS_BY_ROW_ID: + case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: + count = db.update(Tables.CRYPTO_CONSUMERS, values, + buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); + break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); } -- cgit v1.2.3 From 202ccc2c36d191fbecdcc3098875dd075454c71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 1 Jul 2013 23:19:53 +0200 Subject: More work on crypto consumers --- .../src/org/sufficientlysecure/keychain/Id.java | 1 + .../keychain/crypto_provider/CryptoService.java | 9 ++- .../keychain/ui/CryptoConsumersActivity.java | 43 +++++++++++ .../keychain/ui/CryptoConsumersFragment.java | 85 ++++++++++++++++++++++ .../keychain/ui/MainActivity.java | 7 ++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java index 382f144d7..b0d60cf94 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java @@ -62,6 +62,7 @@ public final class Id { public static final int import_from_file = 0x21070020; public static final int import_from_qr_code = 0x21070021; public static final int import_from_nfc = 0x21070022; + public static final int crypto_consumers = 0x21070023; } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java index 7ff8c0e3e..e601620ea 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java @@ -184,7 +184,7 @@ public class CryptoService extends Service { signatureSuccess, signatureUnknown); // return over handler on client side - callback.onDecryptVerifySuccess(outputBytes, sigResult); + callback.onSuccess(outputBytes, sigResult); } catch (Exception e) { Log.e(Constants.TAG, "KeychainService, Exception!", e); @@ -250,6 +250,13 @@ public class CryptoService extends Service { checkAndEnqueue(r); } + @Override + public void setup(boolean asciiArmor, boolean newKeyring, String newKeyringUserId) + throws RemoteException { + // TODO Auto-generated method stub + + } + }; private final IServiceActivityCallback.Stub mBinderServiceActivity = new IServiceActivityCallback.Stub() { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java new file mode 100644 index 000000000..59eaa063f --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java @@ -0,0 +1,43 @@ +package org.sufficientlysecure.keychain.ui; + +import org.sufficientlysecure.keychain.R; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.MenuItem; + +import android.content.Intent; +import android.os.Bundle; + +public class CryptoConsumersActivity extends SherlockFragmentActivity { + private ActionBar mActionBar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mActionBar = getSupportActionBar(); + + setContentView(R.layout.crypto_consumers_activity); + + mActionBar.setDisplayShowTitleEnabled(true); + mActionBar.setDisplayHomeAsUpEnabled(true); + } + + /** + * Menu Options + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // app icon in Action Bar clicked; go home + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java new file mode 100644 index 000000000..8ecc5ced1 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java @@ -0,0 +1,85 @@ +package org.sufficientlysecure.keychain.ui; + +import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.util.Log; + +import com.actionbarsherlock.app.SherlockListFragment; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.widget.SimpleCursorAdapter; + +import android.view.View; +import android.widget.ListView; + +public class CryptoConsumersFragment extends SherlockListFragment implements + LoaderManager.LoaderCallbacks { + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("TODO no crypto consumers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, + null, new String[] { CryptoConsumers.PACKAGE_NAME, CryptoConsumers.PACKAGE_NAME }, + new int[] { android.R.id.text1, android.R.id.text2 }, 0); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, + CryptoConsumers.PACKAGE_NAME }; + + public Loader onCreateLoader(int id, Bundle args) { + // 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. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri = CryptoConsumers.CONTENT_URI; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, + CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java index 447801e55..a108b3db4 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -80,6 +80,9 @@ public class MainActivity extends SherlockActivity { menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences) .setIcon(R.drawable.ic_menu_settings) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + menu.add(0, Id.menu.option.crypto_consumers, 0, R.string.menu_crypto_consumers) + .setIcon(R.drawable.ic_menu_settings) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; } @@ -91,6 +94,10 @@ public class MainActivity extends SherlockActivity { startActivity(new Intent(this, PreferencesActivity.class)); return true; + case Id.menu.option.crypto_consumers: + startActivity(new Intent(this, CryptoConsumersActivity.class)); + return true; + default: break; -- cgit v1.2.3 From 14350679d1ef17fe1add86b1ec1def99f9a8f0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 1 Jul 2013 23:23:53 +0200 Subject: Restructure --- .../keychain/crypto_provider/CryptoService.java | 366 -------------------- .../crypto_provider/IServiceActivityCallback.aidl | 28 -- .../keychain/crypto_provider/ServiceActivity.java | 198 ----------- .../remote_api/CryptoConsumersActivity.java | 44 +++ .../remote_api/CryptoConsumersFragment.java | 85 +++++ .../keychain/remote_api/CryptoService.java | 367 +++++++++++++++++++++ .../remote_api/IServiceActivityCallback.aidl | 28 ++ .../keychain/remote_api/ServiceActivity.java | 199 +++++++++++ .../keychain/ui/CryptoConsumersActivity.java | 43 --- .../keychain/ui/CryptoConsumersFragment.java | 85 ----- .../keychain/ui/MainActivity.java | 1 + 11 files changed, 724 insertions(+), 720 deletions(-) delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java deleted file mode 100644 index e601620ea..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.crypto_provider; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.openintents.crypto.CryptoError; -import org.openintents.crypto.CryptoSignatureResult; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.util.InputData; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor; - -import org.openintents.crypto.ICryptoCallback; -import org.openintents.crypto.ICryptoService; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; - -public class CryptoService extends Service { - Context mContext; - - // just one pool of 4 threads, pause on every user action needed - final ArrayBlockingQueue mPoolQueue = new ArrayBlockingQueue(20); - PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10, - TimeUnit.SECONDS, mPoolQueue); - - public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"; - - @Override - public void onCreate() { - super.onCreate(); - mContext = this; - Log.d(Constants.TAG, "CryptoService, onCreate()"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - Log.d(Constants.TAG, "CryptoService, onDestroy()"); - } - - @Override - public IBinder onBind(Intent intent) { - // return different binder for connections from internal service activity - if (ACTION_SERVICE_ACTIVITY.equals(intent.getAction())) { - String callingPackageName = intent.getPackage(); - - // this binder can only be used from OpenPGP Keychain - if (callingPackageName.equals(Constants.PACKAGE_NAME)) { - return mBinderServiceActivity; - } else { - Log.e(Constants.TAG, "This binder can only be used from " + Constants.PACKAGE_NAME); - return null; - } - } else { - return mBinder; - } - } - - private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds, - ICryptoCallback callback) throws RemoteException { - try { - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); - - OutputStream outStream = new ByteArrayOutputStream(); - - // TODO: hardcoded... - boolean useAsciiArmor = true; - int compressionId = 2; // zlib - - // PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor, - // compressionId, encryptionKeyIds, encryptionPassphrase, Preferences - // .getPreferences(this).getDefaultEncryptionAlgorithm(), - // secretKeyId, - // Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences - // .getPreferences(this).getForceV3Signatures(), - // PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); - - outStream.close(); - } catch (Exception e) { - Log.e(Constants.TAG, "KeychainService, Exception!", e); - - try { - callback.onError(new CryptoError(0, e.getMessage())); - } catch (Exception t) { - Log.e(Constants.TAG, "Error returning exception to client", t); - } - } - } - - private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) - throws RemoteException { - try { - // build InputData and write into OutputStream - InputStream inputStream = new ByteArrayInputStream(inputBytes); - long inputLength = inputBytes.length; - InputData inputData = new InputData(inputStream, inputLength); - - OutputStream outputStream = new ByteArrayOutputStream(); - - long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream); - if (secretKeyId == Id.key.none) { - throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound)); - } - - Log.d(Constants.TAG, "Got input:\n" + new String(inputBytes)); - - Log.d(Constants.TAG, "secretKeyId " + secretKeyId); - - String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, secretKeyId); - - if (passphrase == null) { - Log.d(Constants.TAG, "No passphrase! Activity required!"); - - // start passphrase dialog - Bundle extras = new Bundle(); - extras.putLong(ServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_CACHE_PASSPHRASE, extras); - } - - // if (signedOnly) { - // resultData = PgpMain.verifyText(this, this, inputData, outStream, - // lookupUnknownKey); - // } else { - // resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream, - // PassphraseCacheService.getCachedPassphrase(this, secretKeyId), - // assumeSymmetricEncryption); - // } - - Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, outputStream, - passphrase, false); - - outputStream.close(); - - byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - - // get signature informations from bundle - boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE); - long signatureKeyId = outputBundle - .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID); - String signatureUserId = outputBundle - .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID); - boolean signatureSuccess = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS); - boolean signatureUnknown = outputBundle - .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN); - - CryptoSignatureResult sigResult = new CryptoSignatureResult(signatureUserId, signature, - signatureSuccess, signatureUnknown); - - // return over handler on client side - callback.onSuccess(outputBytes, sigResult); - } catch (Exception e) { - Log.e(Constants.TAG, "KeychainService, Exception!", e); - - try { - callback.onError(new CryptoError(0, e.getMessage())); - } catch (Exception t) { - Log.e(Constants.TAG, "Error returning exception to client", t); - } - } - } - - private final ICryptoService.Stub mBinder = new ICryptoService.Stub() { - - @Override - public void encrypt(final byte[] inputBytes, final String[] encryptionUserIds, - final ICryptoCallback callback) throws RemoteException { - - Runnable r = new Runnable() { - - @Override - public void run() { - try { - encryptSafe(inputBytes, encryptionUserIds, callback); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoService", e); - } - } - }; - - checkAndEnqueue(r); - } - - @Override - public void encryptAndSign(byte[] inputBytes, String[] encryptionUserIds, - String signatureUserId, ICryptoCallback callback) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void sign(byte[] inputBytes, String signatureUserId, ICryptoCallback callback) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void decryptAndVerify(final byte[] inputBytes, final ICryptoCallback callback) - throws RemoteException { - - Runnable r = new Runnable() { - - @Override - public void run() { - try { - decryptAndVerifySafe(inputBytes, callback); - } catch (RemoteException e) { - Log.e(Constants.TAG, "CryptoService", e); - } - } - }; - - checkAndEnqueue(r); - } - - @Override - public void setup(boolean asciiArmor, boolean newKeyring, String newKeyringUserId) - throws RemoteException { - // TODO Auto-generated method stub - - } - - }; - - private final IServiceActivityCallback.Stub mBinderServiceActivity = new IServiceActivityCallback.Stub() { - - @Override - public void register(boolean success, String packageName) throws RemoteException { - - if (success) { - // resume threads - if (isPackageAllowed(packageName)) { - mThreadPool.resume(); - } else { - // TODO: should not happen? - } - } else { - // TODO - mPoolQueue.clear(); - } - - } - - @Override - public void cachePassphrase(boolean success, String passphrase) throws RemoteException { - - } - - }; - - private void checkAndEnqueue(Runnable r) { - if (isCallerAllowed()) { - mThreadPool.execute(r); - - Log.d(Constants.TAG, "Enqueued runnable…"); - } else { - String[] callingPackages = getPackageManager() - .getPackagesForUid(Binder.getCallingUid()); - - Log.e(Constants.TAG, "Not allowed to use service! Starting activity for registration!"); - Bundle extras = new Bundle(); - // TODO: currently simply uses first entry - extras.putString(ServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]); - pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, extras); - - mThreadPool.execute(r); - - Log.d(Constants.TAG, "Enqueued runnable…"); - } - } - - /** - * Checks if process that binds to this service (i.e. the package name corresponding to the - * process) is in the list of allowed package names. - * - * @return true if process is allowed to use this service - */ - private boolean isCallerAllowed() { - String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); - - // is calling package allowed to use this service? - for (int i = 0; i < callingPackages.length; i++) { - String currentPkg = callingPackages[i]; - - if (isPackageAllowed(currentPkg)) { - return true; - } - } - - Log.d(Constants.TAG, "Caller is NOT allowed!"); - return false; - } - - private boolean isPackageAllowed(String packageName) { - Log.d(Constants.TAG, "packageName: " + packageName); - - ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(mContext); - Log.d(Constants.TAG, "allowed: " + allowedPkgs); - - // check if package is allowed to use our service - if (allowedPkgs.contains(packageName)) { - Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); - - return true; - } else if (Constants.PACKAGE_NAME.equals(packageName)) { - Log.d(Constants.TAG, "Package is OpenPGP Keychain! -> allowed!"); - - return true; - } - - return false; - } - - private void pauseQueueAndStartServiceActivity(String action, Bundle extras) { - mThreadPool.pause(); - - Log.d(Constants.TAG, "starting activity..."); - Intent intent = new Intent(getBaseContext(), ServiceActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); - intent.setAction(action); - if (extras != null) { - intent.putExtras(extras); - } - getApplication().startActivity(intent); - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl deleted file mode 100644 index 61a8da06c..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/IServiceActivityCallback.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.crypto_provider; - - -interface IServiceActivityCallback { - - - oneway void register(in boolean success, in String packageName); - - oneway void cachePassphrase(in boolean success, in String passphrase); - - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java deleted file mode 100644 index 7efce85c7..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/ServiceActivity.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.crypto_provider; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import com.actionbarsherlock.app.SherlockFragmentActivity; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class ServiceActivity extends SherlockFragmentActivity { - - public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; - public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; - - public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; - public static final String EXTRA_PACKAGE_NAME = "packageName"; - - private IServiceActivityCallback mService; - private boolean mServiceBound; - - private ServiceConnection mServiceActivityConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - mService = IServiceActivityCallback.Stub.asInterface(service); - Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); - mServiceBound = true; - } - - public void onServiceDisconnected(ComponentName name) { - mService = null; - Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); - mServiceBound = false; - } - }; - - /** - * If not already bound, bind! - * - * @return - */ - public boolean bindToService() { - if (mService == null && !mServiceBound) { // if not already connected - try { - Log.d(Constants.TAG, "not bound yet"); - - Intent serviceIntent = new Intent(); - serviceIntent.setAction("org.openintents.crypto.ICryptoService"); - bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); - - return true; - } catch (Exception e) { - Log.d(Constants.TAG, "Exception", e); - return false; - } - } else { // already connected - Log.d(Constants.TAG, "already bound... "); - return true; - } - } - - public void unbindFromService() { - unbindService(mServiceActivityConnection); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d(Constants.TAG, "onCreate…"); - - // bind to our own crypto service - bindToService(); - - handleActions(getIntent()); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - // unbind from our crypto service - if (mServiceActivityConnection != null) { - unbindFromService(); - } - } - - protected void handleActions(Intent intent) { - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - /** - * com.android.crypto actions - */ - if (ACTION_REGISTER.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - - setContentView(R.layout.register_crypto_consumer_activity); - - Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); - Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); - - allowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); - // Intent data = new Intent(); - - setResult(RESULT_OK); - finish(); - } - }); - - disallowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }); - } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { - long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); - - showPassphraseDialog(secretKeyId); - } else { - Log.e(Constants.TAG, "Wrong action!"); - setResult(RESULT_CANCELED); - finish(); - } - } - - /** - * Shows passphrase dialog to cache a new passphrase the user enters for using it later for - * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks - * for a symmetric passphrase - */ - private void showPassphraseDialog(long secretKeyId) { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - setResult(RESULT_OK); - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - try { - PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, - messenger, secretKeyId); - - passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PgpMain.PgpGeneralException e) { - Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); - // send message to handler to start encryption directly - returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); - } - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java new file mode 100644 index 000000000..e3aa0ed49 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java @@ -0,0 +1,44 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.MainActivity; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.MenuItem; + +import android.content.Intent; +import android.os.Bundle; + +public class CryptoConsumersActivity extends SherlockFragmentActivity { + private ActionBar mActionBar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mActionBar = getSupportActionBar(); + + setContentView(R.layout.crypto_consumers_activity); + + mActionBar.setDisplayShowTitleEnabled(true); + mActionBar.setDisplayHomeAsUpEnabled(true); + } + + /** + * Menu Options + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // app icon in Action Bar clicked; go home + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java new file mode 100644 index 000000000..935d64560 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java @@ -0,0 +1,85 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.util.Log; + +import com.actionbarsherlock.app.SherlockListFragment; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.widget.SimpleCursorAdapter; + +import android.view.View; +import android.widget.ListView; + +public class CryptoConsumersFragment extends SherlockListFragment implements + LoaderManager.LoaderCallbacks { + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("TODO no crypto consumers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, + null, new String[] { CryptoConsumers.PACKAGE_NAME, CryptoConsumers.PACKAGE_NAME }, + new int[] { android.R.id.text1, android.R.id.text2 }, 0); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, + CryptoConsumers.PACKAGE_NAME }; + + public Loader onCreateLoader(int id, Bundle args) { + // 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. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri = CryptoConsumers.CONTENT_URI; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, + CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java new file mode 100644 index 000000000..c7d40d376 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.remote_api; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.openintents.crypto.CryptoError; +import org.openintents.crypto.CryptoSignatureResult; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; +import org.sufficientlysecure.keychain.helper.PgpMain; +import org.sufficientlysecure.keychain.util.InputData; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor; + +import org.openintents.crypto.ICryptoCallback; +import org.openintents.crypto.ICryptoService; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; + +public class CryptoService extends Service { + Context mContext; + + // just one pool of 4 threads, pause on every user action needed + final ArrayBlockingQueue mPoolQueue = new ArrayBlockingQueue(20); + PausableThreadPoolExecutor mThreadPool = new PausableThreadPoolExecutor(2, 4, 10, + TimeUnit.SECONDS, mPoolQueue); + + public static final String ACTION_SERVICE_ACTIVITY = "org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"; + + @Override + public void onCreate() { + super.onCreate(); + mContext = this; + Log.d(Constants.TAG, "CryptoService, onCreate()"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.d(Constants.TAG, "CryptoService, onDestroy()"); + } + + @Override + public IBinder onBind(Intent intent) { + // return different binder for connections from internal service activity + if (ACTION_SERVICE_ACTIVITY.equals(intent.getAction())) { + String callingPackageName = intent.getPackage(); + + // this binder can only be used from OpenPGP Keychain + if (callingPackageName.equals(Constants.PACKAGE_NAME)) { + return mBinderServiceActivity; + } else { + Log.e(Constants.TAG, "This binder can only be used from " + Constants.PACKAGE_NAME); + return null; + } + } else { + return mBinder; + } + } + + private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds, + ICryptoCallback callback) throws RemoteException { + try { + // build InputData and write into OutputStream + InputStream inputStream = new ByteArrayInputStream(inputBytes); + long inputLength = inputBytes.length; + InputData inputData = new InputData(inputStream, inputLength); + + OutputStream outStream = new ByteArrayOutputStream(); + + // TODO: hardcoded... + boolean useAsciiArmor = true; + int compressionId = 2; // zlib + + // PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor, + // compressionId, encryptionKeyIds, encryptionPassphrase, Preferences + // .getPreferences(this).getDefaultEncryptionAlgorithm(), + // secretKeyId, + // Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences + // .getPreferences(this).getForceV3Signatures(), + // PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); + + outStream.close(); + } catch (Exception e) { + Log.e(Constants.TAG, "KeychainService, Exception!", e); + + try { + callback.onError(new CryptoError(0, e.getMessage())); + } catch (Exception t) { + Log.e(Constants.TAG, "Error returning exception to client", t); + } + } + } + + private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) + throws RemoteException { + try { + // build InputData and write into OutputStream + InputStream inputStream = new ByteArrayInputStream(inputBytes); + long inputLength = inputBytes.length; + InputData inputData = new InputData(inputStream, inputLength); + + OutputStream outputStream = new ByteArrayOutputStream(); + + long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream); + if (secretKeyId == Id.key.none) { + throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound)); + } + + Log.d(Constants.TAG, "Got input:\n" + new String(inputBytes)); + + Log.d(Constants.TAG, "secretKeyId " + secretKeyId); + + String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, secretKeyId); + + if (passphrase == null) { + Log.d(Constants.TAG, "No passphrase! Activity required!"); + + // start passphrase dialog + Bundle extras = new Bundle(); + extras.putLong(ServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); + pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_CACHE_PASSPHRASE, extras); + } + + // if (signedOnly) { + // resultData = PgpMain.verifyText(this, this, inputData, outStream, + // lookupUnknownKey); + // } else { + // resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream, + // PassphraseCacheService.getCachedPassphrase(this, secretKeyId), + // assumeSymmetricEncryption); + // } + + Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, outputStream, + passphrase, false); + + outputStream.close(); + + byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); + + // get signature informations from bundle + boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE); + long signatureKeyId = outputBundle + .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID); + String signatureUserId = outputBundle + .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID); + boolean signatureSuccess = outputBundle + .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS); + boolean signatureUnknown = outputBundle + .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN); + + CryptoSignatureResult sigResult = new CryptoSignatureResult(signatureUserId, signature, + signatureSuccess, signatureUnknown); + + // return over handler on client side + callback.onSuccess(outputBytes, sigResult); + } catch (Exception e) { + Log.e(Constants.TAG, "KeychainService, Exception!", e); + + try { + callback.onError(new CryptoError(0, e.getMessage())); + } catch (Exception t) { + Log.e(Constants.TAG, "Error returning exception to client", t); + } + } + } + + private final ICryptoService.Stub mBinder = new ICryptoService.Stub() { + + @Override + public void encrypt(final byte[] inputBytes, final String[] encryptionUserIds, + final ICryptoCallback callback) throws RemoteException { + + Runnable r = new Runnable() { + + @Override + public void run() { + try { + encryptSafe(inputBytes, encryptionUserIds, callback); + } catch (RemoteException e) { + Log.e(Constants.TAG, "CryptoService", e); + } + } + }; + + checkAndEnqueue(r); + } + + @Override + public void encryptAndSign(byte[] inputBytes, String[] encryptionUserIds, + String signatureUserId, ICryptoCallback callback) throws RemoteException { + // TODO Auto-generated method stub + + } + + @Override + public void sign(byte[] inputBytes, String signatureUserId, ICryptoCallback callback) + throws RemoteException { + // TODO Auto-generated method stub + + } + + @Override + public void decryptAndVerify(final byte[] inputBytes, final ICryptoCallback callback) + throws RemoteException { + + Runnable r = new Runnable() { + + @Override + public void run() { + try { + decryptAndVerifySafe(inputBytes, callback); + } catch (RemoteException e) { + Log.e(Constants.TAG, "CryptoService", e); + } + } + }; + + checkAndEnqueue(r); + } + + @Override + public void setup(boolean asciiArmor, boolean newKeyring, String newKeyringUserId) + throws RemoteException { + // TODO Auto-generated method stub + + } + + }; + + private final IServiceActivityCallback.Stub mBinderServiceActivity = new IServiceActivityCallback.Stub() { + + @Override + public void register(boolean success, String packageName) throws RemoteException { + + if (success) { + // resume threads + if (isPackageAllowed(packageName)) { + mThreadPool.resume(); + } else { + // TODO: should not happen? + } + } else { + // TODO + mPoolQueue.clear(); + } + + } + + @Override + public void cachePassphrase(boolean success, String passphrase) throws RemoteException { + + } + + }; + + private void checkAndEnqueue(Runnable r) { + if (isCallerAllowed()) { + mThreadPool.execute(r); + + Log.d(Constants.TAG, "Enqueued runnable…"); + } else { + String[] callingPackages = getPackageManager() + .getPackagesForUid(Binder.getCallingUid()); + + Log.e(Constants.TAG, "Not allowed to use service! Starting activity for registration!"); + Bundle extras = new Bundle(); + // TODO: currently simply uses first entry + extras.putString(ServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]); + pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, extras); + + mThreadPool.execute(r); + + Log.d(Constants.TAG, "Enqueued runnable…"); + } + } + + /** + * Checks if process that binds to this service (i.e. the package name corresponding to the + * process) is in the list of allowed package names. + * + * @return true if process is allowed to use this service + */ + private boolean isCallerAllowed() { + String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); + + // is calling package allowed to use this service? + for (int i = 0; i < callingPackages.length; i++) { + String currentPkg = callingPackages[i]; + + if (isPackageAllowed(currentPkg)) { + return true; + } + } + + Log.d(Constants.TAG, "Caller is NOT allowed!"); + return false; + } + + private boolean isPackageAllowed(String packageName) { + Log.d(Constants.TAG, "packageName: " + packageName); + + ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(mContext); + Log.d(Constants.TAG, "allowed: " + allowedPkgs); + + // check if package is allowed to use our service + if (allowedPkgs.contains(packageName)) { + Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + + return true; + } else if (Constants.PACKAGE_NAME.equals(packageName)) { + Log.d(Constants.TAG, "Package is OpenPGP Keychain! -> allowed!"); + + return true; + } + + return false; + } + + private void pauseQueueAndStartServiceActivity(String action, Bundle extras) { + mThreadPool.pause(); + + Log.d(Constants.TAG, "starting activity..."); + Intent intent = new Intent(getBaseContext(), ServiceActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + intent.setAction(action); + if (extras != null) { + intent.putExtras(extras); + } + getApplication().startActivity(intent); + } + +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl new file mode 100644 index 000000000..871560cc8 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.remote_api; + + +interface IServiceActivityCallback { + + + oneway void register(in boolean success, in String packageName); + + oneway void cachePassphrase(in boolean success, in String passphrase); + + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java new file mode 100644 index 000000000..055de9be1 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; +import org.sufficientlysecure.keychain.helper.PgpMain; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Log; + +import com.actionbarsherlock.app.SherlockFragmentActivity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class ServiceActivity extends SherlockFragmentActivity { + + public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; + public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; + + public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; + public static final String EXTRA_PACKAGE_NAME = "packageName"; + + private IServiceActivityCallback mService; + private boolean mServiceBound; + + private ServiceConnection mServiceActivityConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = IServiceActivityCallback.Stub.asInterface(service); + Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); + mServiceBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mService = null; + Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); + mServiceBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mService == null && !mServiceBound) { // if not already connected + try { + Log.d(Constants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent.setAction("org.openintents.crypto.ICryptoService"); + bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(Constants.TAG, "Exception", e); + return false; + } + } else { // already connected + Log.d(Constants.TAG, "already bound... "); + return true; + } + } + + public void unbindFromService() { + unbindService(mServiceActivityConnection); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.d(Constants.TAG, "onCreate…"); + + // bind to our own crypto service + bindToService(); + + handleActions(getIntent()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // unbind from our crypto service + if (mServiceActivityConnection != null) { + unbindFromService(); + } + } + + protected void handleActions(Intent intent) { + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + /** + * com.android.crypto actions + */ + if (ACTION_REGISTER.equals(action)) { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + + setContentView(R.layout.register_crypto_consumer_activity); + + Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); + Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); + + allowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); + // Intent data = new Intent(); + + setResult(RESULT_OK); + finish(); + } + }); + + disallowButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }); + } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { + long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); + + showPassphraseDialog(secretKeyId); + } else { + Log.e(Constants.TAG, "Wrong action!"); + setResult(RESULT_CANCELED); + finish(); + } + } + + /** + * Shows passphrase dialog to cache a new passphrase the user enters for using it later for + * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks + * for a symmetric passphrase + */ + private void showPassphraseDialog(long secretKeyId) { + // Message is received after passphrase is cached + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + setResult(RESULT_OK); + finish(); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + try { + PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, + messenger, secretKeyId); + + passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); + } catch (PgpMain.PgpGeneralException e) { + Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); + // send message to handler to start encryption directly + returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); + } + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java deleted file mode 100644 index 59eaa063f..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersActivity.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.sufficientlysecure.keychain.ui; - -import org.sufficientlysecure.keychain.R; - -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.MenuItem; - -import android.content.Intent; -import android.os.Bundle; - -public class CryptoConsumersActivity extends SherlockFragmentActivity { - private ActionBar mActionBar; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mActionBar = getSupportActionBar(); - - setContentView(R.layout.crypto_consumers_activity); - - mActionBar.setDisplayShowTitleEnabled(true); - mActionBar.setDisplayHomeAsUpEnabled(true); - } - - /** - * Menu Options - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - // app icon in Action Bar clicked; go home - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java deleted file mode 100644 index 8ecc5ced1..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/CryptoConsumersFragment.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.sufficientlysecure.keychain.ui; - -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; -import org.sufficientlysecure.keychain.util.Log; - -import com.actionbarsherlock.app.SherlockListFragment; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; -import android.support.v4.widget.SimpleCursorAdapter; - -import android.view.View; -import android.widget.ListView; - -public class CryptoConsumersFragment extends SherlockListFragment implements - LoaderManager.LoaderCallbacks { - - // This is the Adapter being used to display the list's data. - SimpleCursorAdapter mAdapter; - - // If non-null, this is the current filter the user has provided. - String mCurFilter; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - // Give some text to display if there is no data. In a real - // application this would come from a resource. - setEmptyText("TODO no crypto consumers"); - - // We have a menu item to show in action bar. - setHasOptionsMenu(true); - - // Create an empty adapter we will use to display the loaded data. - mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, - null, new String[] { CryptoConsumers.PACKAGE_NAME, CryptoConsumers.PACKAGE_NAME }, - new int[] { android.R.id.text1, android.R.id.text2 }, 0); - setListAdapter(mAdapter); - - // Prepare the loader. Either re-connect with an existing one, - // or start a new one. - getLoaderManager().initLoader(0, null, this); - } - - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - // Insert desired behavior here. - Log.i("FragmentComplexList", "Item clicked: " + id); - } - - // These are the Contacts rows that we will retrieve. - static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, - CryptoConsumers.PACKAGE_NAME }; - - public Loader onCreateLoader(int id, Bundle args) { - // 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. - // First, pick the base URI to use depending on whether we are - // currently filtering. - Uri baseUri = CryptoConsumers.CONTENT_URI; - - // Now create and return a CursorLoader that will take care of - // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, - CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); - } - - public void onLoadFinished(Loader loader, Cursor data) { - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - mAdapter.swapCursor(data); - } - - public void onLoaderReset(Loader loader) { - // This is called when the last Cursor provided to onLoadFinished() - // above is about to be closed. We need to make sure we are no - // longer using it. - mAdapter.swapCursor(null); - } - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java index a108b3db4..434db7a29 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.remote_api.CryptoConsumersActivity; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; -- cgit v1.2.3 From 7cca7b1ffa416a354c08e1cb6b5776ae55fc19ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 25 Jul 2013 16:25:20 +0200 Subject: Redifine Service callbacks --- .../remote_api/CryptoConsumersActivity.java | 2 +- .../keychain/remote_api/CryptoService.java | 6 +-- .../remote_api/IServiceActivityCallback.aidl | 8 ++-- .../keychain/remote_api/ServiceActivity.java | 50 +++++++++++++++++----- 4 files changed, 45 insertions(+), 21 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java index e3aa0ed49..3f12a5e8b 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java @@ -19,7 +19,7 @@ public class CryptoConsumersActivity extends SherlockFragmentActivity { mActionBar = getSupportActionBar(); - setContentView(R.layout.crypto_consumers_activity); + setContentView(R.layout.crypto_consumer_list_activity); mActionBar.setDisplayShowTitleEnabled(true); mActionBar.setDisplayHomeAsUpEnabled(true); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java index c7d40d376..71b78ee01 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java @@ -263,7 +263,7 @@ public class CryptoService extends Service { private final IServiceActivityCallback.Stub mBinderServiceActivity = new IServiceActivityCallback.Stub() { @Override - public void register(boolean success, String packageName) throws RemoteException { + public void onRegistered(boolean success, String packageName) throws RemoteException { if (success) { // resume threads @@ -280,7 +280,7 @@ public class CryptoService extends Service { } @Override - public void cachePassphrase(boolean success, String passphrase) throws RemoteException { + public void onCachedPassphrase(boolean success) throws RemoteException { } @@ -355,8 +355,6 @@ public class CryptoService extends Service { Log.d(Constants.TAG, "starting activity..."); Intent intent = new Intent(getBaseContext(), ServiceActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - // intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.setAction(action); if (extras != null) { intent.putExtras(extras); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl index 871560cc8..e9949e1ae 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/IServiceActivityCallback.aidl @@ -19,10 +19,8 @@ package org.sufficientlysecure.keychain.remote_api; interface IServiceActivityCallback { + oneway void onRegistered(in boolean success, in String packageName); - oneway void register(in boolean success, in String packageName); - - oneway void cachePassphrase(in boolean success, in String passphrase); - - + oneway void onCachedPassphrase(in boolean success); + } \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 055de9be1..981568944 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -16,6 +16,8 @@ package org.sufficientlysecure.keychain.remote_api; +import java.util.ArrayList; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; @@ -35,30 +37,32 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; +import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; +import android.widget.LinearLayout; public class ServiceActivity extends SherlockFragmentActivity { - public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.REGISTER"; - public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE"; + public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.remote_api.REGISTER"; + public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.remote_api.CRYPTO_CACHE_PASSPHRASE"; public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; public static final String EXTRA_PACKAGE_NAME = "packageName"; - private IServiceActivityCallback mService; + private IServiceActivityCallback mServiceCallback; private boolean mServiceBound; private ServiceConnection mServiceActivityConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { - mService = IServiceActivityCallback.Stub.asInterface(service); + mServiceCallback = IServiceActivityCallback.Stub.asInterface(service); Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); mServiceBound = true; } public void onServiceDisconnected(ComponentName name) { - mService = null; + mServiceCallback = null; Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); mServiceBound = false; } @@ -70,7 +74,7 @@ public class ServiceActivity extends SherlockFragmentActivity { * @return */ public boolean bindToService() { - if (mService == null && !mServiceBound) { // if not already connected + if (mServiceCallback == null && !mServiceBound) { // if not already connected try { Log.d(Constants.TAG, "not bound yet"); @@ -129,7 +133,20 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - setContentView(R.layout.register_crypto_consumer_activity); + setContentView(R.layout.crypto_consumer_register_activity); + LinearLayout layoutRegister = (LinearLayout) findViewById(R.id.register_crypto_consumer_register_layout); + LinearLayout layoutEdit = (LinearLayout) findViewById(R.id.register_crypto_consumer_edit_layout); + + // if already registered show edit buttons + ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(this); + if (allowedPkgs.contains(packageName)) { + Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + layoutRegister.setVisibility(View.GONE); + layoutEdit.setVisibility(View.VISIBLE); + } else { + layoutRegister.setVisibility(View.VISIBLE); + layoutEdit.setVisibility(View.GONE); + } Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); @@ -141,7 +158,11 @@ public class ServiceActivity extends SherlockFragmentActivity { ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); // Intent data = new Intent(); - setResult(RESULT_OK); + try { + mServiceCallback.onRegistered(true, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } finish(); } }); @@ -150,7 +171,11 @@ public class ServiceActivity extends SherlockFragmentActivity { @Override public void onClick(View v) { - setResult(RESULT_CANCELED); + try { + mServiceCallback.onRegistered(false, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } finish(); } }); @@ -160,7 +185,6 @@ public class ServiceActivity extends SherlockFragmentActivity { showPassphraseDialog(secretKeyId); } else { Log.e(Constants.TAG, "Wrong action!"); - setResult(RESULT_CANCELED); finish(); } } @@ -176,7 +200,11 @@ public class ServiceActivity extends SherlockFragmentActivity { @Override public void handleMessage(Message message) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - setResult(RESULT_OK); + try { + mServiceCallback.onCachedPassphrase(true); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } finish(); } } -- cgit v1.2.3 From c3b49a318f82238245f6c40b7a8abda01cb9433d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 4 Sep 2013 20:12:58 +0200 Subject: Show app name in registered apps --- .../remote_api/CryptoConsumersActivity.java | 44 ----------- .../remote_api/CryptoConsumersFragment.java | 85 --------------------- .../keychain/remote_api/RegisteredAppsAdapter.java | 72 +++++++++++++++++ .../remote_api/RegisteredAppsFragment.java | 83 ++++++++++++++++++++ .../remote_api/RegisteredAppsListActivity.java | 44 +++++++++++ .../keychain/remote_api/ServiceActivity.java | 2 +- .../ui/.SelectSecretKeyFragment.java.kate-swp | Bin 0 -> 64 bytes .../keychain/ui/MainActivity.java | 6 +- 8 files changed, 203 insertions(+), 133 deletions(-) delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/.SelectSecretKeyFragment.java.kate-swp (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java deleted file mode 100644 index 3f12a5e8b..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersActivity.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sufficientlysecure.keychain.remote_api; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.MainActivity; - -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.MenuItem; - -import android.content.Intent; -import android.os.Bundle; - -public class CryptoConsumersActivity extends SherlockFragmentActivity { - private ActionBar mActionBar; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mActionBar = getSupportActionBar(); - - setContentView(R.layout.crypto_consumer_list_activity); - - mActionBar.setDisplayShowTitleEnabled(true); - mActionBar.setDisplayHomeAsUpEnabled(true); - } - - /** - * Menu Options - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - // app icon in Action Bar clicked; go home - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java deleted file mode 100644 index 935d64560..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoConsumersFragment.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.sufficientlysecure.keychain.remote_api; - -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; -import org.sufficientlysecure.keychain.util.Log; - -import com.actionbarsherlock.app.SherlockListFragment; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; -import android.support.v4.widget.SimpleCursorAdapter; - -import android.view.View; -import android.widget.ListView; - -public class CryptoConsumersFragment extends SherlockListFragment implements - LoaderManager.LoaderCallbacks { - - // This is the Adapter being used to display the list's data. - SimpleCursorAdapter mAdapter; - - // If non-null, this is the current filter the user has provided. - String mCurFilter; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - // Give some text to display if there is no data. In a real - // application this would come from a resource. - setEmptyText("TODO no crypto consumers"); - - // We have a menu item to show in action bar. - setHasOptionsMenu(true); - - // Create an empty adapter we will use to display the loaded data. - mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, - null, new String[] { CryptoConsumers.PACKAGE_NAME, CryptoConsumers.PACKAGE_NAME }, - new int[] { android.R.id.text1, android.R.id.text2 }, 0); - setListAdapter(mAdapter); - - // Prepare the loader. Either re-connect with an existing one, - // or start a new one. - getLoaderManager().initLoader(0, null, this); - } - - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - // Insert desired behavior here. - Log.i("FragmentComplexList", "Item clicked: " + id); - } - - // These are the Contacts rows that we will retrieve. - static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, - CryptoConsumers.PACKAGE_NAME }; - - public Loader onCreateLoader(int id, Bundle args) { - // 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. - // First, pick the base URI to use depending on whether we are - // currently filtering. - Uri baseUri = CryptoConsumers.CONTENT_URI; - - // Now create and return a CursorLoader that will take care of - // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, - CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); - } - - public void onLoadFinished(Loader loader, Cursor data) { - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - mAdapter.swapCursor(data); - } - - public void onLoaderReset(Loader loader) { - // This is called when the last Cursor provided to onLoadFinished() - // above is about to be closed. We need to make sure we are no - // longer using it. - mAdapter.swapCursor(null); - } - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java new file mode 100644 index 000000000..61888ad5a --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.database.Cursor; +import android.support.v4.widget.CursorAdapter; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class RegisteredAppsAdapter extends CursorAdapter { + + private LayoutInflater mInflater; + private PackageManager pm; + + @SuppressWarnings("deprecation") + public RegisteredAppsAdapter(Context context, Cursor c) { + super(context, c); + + mInflater = LayoutInflater.from(context); + pm = context.getApplicationContext().getPackageManager(); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + TextView text1 = (TextView) view.findViewById(android.R.id.text1); + TextView text2 = (TextView) view.findViewById(android.R.id.text2); + + String packageName = cursor.getString(cursor.getColumnIndex(CryptoConsumers.PACKAGE_NAME)); + if (packageName != null) { + text2.setText(packageName); + + // get application name + try { + ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); + + text1.setText(pm.getApplicationLabel(ai)); + } catch (final NameNotFoundException e) { + text1.setText(R.string.api_unknown_app); + } + } + + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return mInflater.inflate(android.R.layout.simple_list_item_2, null); + } + +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java new file mode 100644 index 000000000..b8fd649b4 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java @@ -0,0 +1,83 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.util.Log; + +import com.actionbarsherlock.app.SherlockListFragment; + +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.View; +import android.widget.ListView; + +public class RegisteredAppsFragment extends SherlockListFragment implements + LoaderManager.LoaderCallbacks { + + // This is the Adapter being used to display the list's data. + RegisteredAppsAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText(getString(R.string.api_no_apps)); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new RegisteredAppsAdapter(getActivity(), null); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, + CryptoConsumers.PACKAGE_NAME }; + + public Loader onCreateLoader(int id, Bundle args) { + // 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. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri = CryptoConsumers.CONTENT_URI; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, + CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java new file mode 100644 index 000000000..bf34e14f4 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java @@ -0,0 +1,44 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.MainActivity; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.MenuItem; + +import android.content.Intent; +import android.os.Bundle; + +public class RegisteredAppsListActivity extends SherlockFragmentActivity { + private ActionBar mActionBar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mActionBar = getSupportActionBar(); + + setContentView(R.layout.api_app_settings_list_activity); + + mActionBar.setDisplayShowTitleEnabled(true); + mActionBar.setDisplayHomeAsUpEnabled(true); + } + + /** + * Menu Options + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // app icon in Action Bar clicked; go home + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 981568944..ba09c9f56 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -133,7 +133,7 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - setContentView(R.layout.crypto_consumer_register_activity); + setContentView(R.layout.api_register_activity); LinearLayout layoutRegister = (LinearLayout) findViewById(R.id.register_crypto_consumer_register_layout); LinearLayout layoutEdit = (LinearLayout) findViewById(R.id.register_crypto_consumer_edit_layout); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/.SelectSecretKeyFragment.java.kate-swp b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/.SelectSecretKeyFragment.java.kate-swp new file mode 100644 index 000000000..c72aa8947 Binary files /dev/null and b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/.SelectSecretKeyFragment.java.kate-swp differ diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java index 434db7a29..3f5ca536f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.remote_api.CryptoConsumersActivity; +import org.sufficientlysecure.keychain.remote_api.RegisteredAppsListActivity; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; @@ -81,7 +81,7 @@ public class MainActivity extends SherlockActivity { menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences) .setIcon(R.drawable.ic_menu_settings) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - menu.add(0, Id.menu.option.crypto_consumers, 0, R.string.menu_crypto_consumers) + menu.add(0, Id.menu.option.crypto_consumers, 0, R.string.menu_apiAppSettings) .setIcon(R.drawable.ic_menu_settings) .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; @@ -96,7 +96,7 @@ public class MainActivity extends SherlockActivity { return true; case Id.menu.option.crypto_consumers: - startActivity(new Intent(this, CryptoConsumersActivity.class)); + startActivity(new Intent(this, RegisteredAppsListActivity.class)); return true; default: -- cgit v1.2.3 From d8bd6e29461d30a8638831451b781b8efa7e4a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 4 Sep 2013 22:04:27 +0200 Subject: Settings fragment and activity for apps --- .../keychain/remote_api/AppSettingsActivity.java | 35 ++++++++ .../keychain/remote_api/AppSettingsFragment.java | 20 +++++ .../remote_api/RegisteredAppsFragment.java | 83 ------------------- .../remote_api/RegisteredAppsListActivity.java | 2 +- .../remote_api/RegisteredAppsListFragment.java | 92 ++++++++++++++++++++++ .../keychain/remote_api/ServiceActivity.java | 2 +- 6 files changed, 149 insertions(+), 85 deletions(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java new file mode 100644 index 000000000..31fbdc8a6 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -0,0 +1,35 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class AppSettingsActivity extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.api_app_settings_activity); + + // check if add new or edit existing + Intent intent = getIntent(); + Uri appUri = intent.getData(); + if (appUri == null) { + Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); + finish(); + return; + } + + Log.d(Constants.TAG, "uri: " + appUri); + + + } + +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java new file mode 100644 index 000000000..4bb09d50f --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -0,0 +1,20 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +public class AppSettingsFragment extends Fragment { + + /** + * Inflate the layout for this fragment + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.api_app_settings_fragment, container, false); + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java deleted file mode 100644 index b8fd649b4..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsFragment.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.sufficientlysecure.keychain.remote_api; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; -import org.sufficientlysecure.keychain.util.Log; - -import com.actionbarsherlock.app.SherlockListFragment; - -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; -import android.view.View; -import android.widget.ListView; - -public class RegisteredAppsFragment extends SherlockListFragment implements - LoaderManager.LoaderCallbacks { - - // This is the Adapter being used to display the list's data. - RegisteredAppsAdapter mAdapter; - - // If non-null, this is the current filter the user has provided. - String mCurFilter; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - // Give some text to display if there is no data. In a real - // application this would come from a resource. - setEmptyText(getString(R.string.api_no_apps)); - - // We have a menu item to show in action bar. - setHasOptionsMenu(true); - - // Create an empty adapter we will use to display the loaded data. - mAdapter = new RegisteredAppsAdapter(getActivity(), null); - setListAdapter(mAdapter); - - // Prepare the loader. Either re-connect with an existing one, - // or start a new one. - getLoaderManager().initLoader(0, null, this); - } - - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - // Insert desired behavior here. - Log.i("FragmentComplexList", "Item clicked: " + id); - } - - // These are the Contacts rows that we will retrieve. - static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, - CryptoConsumers.PACKAGE_NAME }; - - public Loader onCreateLoader(int id, Bundle args) { - // 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. - // First, pick the base URI to use depending on whether we are - // currently filtering. - Uri baseUri = CryptoConsumers.CONTENT_URI; - - // Now create and return a CursorLoader that will take care of - // creating a Cursor for the data being displayed. - return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, - CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); - } - - public void onLoadFinished(Loader loader, Cursor data) { - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - mAdapter.swapCursor(data); - } - - public void onLoaderReset(Loader loader) { - // This is called when the last Cursor provided to onLoadFinished() - // above is about to be closed. We need to make sure we are no - // longer using it. - mAdapter.swapCursor(null); - } - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java index bf34e14f4..f5487e2a3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListActivity.java @@ -19,7 +19,7 @@ public class RegisteredAppsListActivity extends SherlockFragmentActivity { mActionBar = getSupportActionBar(); - setContentView(R.layout.api_app_settings_list_activity); + setContentView(R.layout.api_apps_list_activity); mActionBar.setDisplayShowTitleEnabled(true); mActionBar.setDisplayHomeAsUpEnabled(true); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java new file mode 100644 index 000000000..52f4d1398 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java @@ -0,0 +1,92 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; + +import com.actionbarsherlock.app.SherlockListFragment; + +import android.content.ContentUris; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListView; + +public class RegisteredAppsListFragment extends SherlockListFragment implements + LoaderManager.LoaderCallbacks { + + // This is the Adapter being used to display the list's data. + RegisteredAppsAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + getListView().setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int position, long id) { + // edit app settings + Intent intent = new Intent(getActivity(), AppSettingsActivity.class); + intent.setData(ContentUris.withAppendedId( + KeychainContract.CryptoConsumers.CONTENT_URI, id)); + startActivity(intent); + } + }); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText(getString(R.string.api_no_apps)); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new RegisteredAppsAdapter(getActivity(), null); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, + CryptoConsumers.PACKAGE_NAME }; + + public Loader onCreateLoader(int id, Bundle args) { + // 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. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri = CryptoConsumers.CONTENT_URI; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, + CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } + +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index ba09c9f56..5849fb80d 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -133,7 +133,7 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - setContentView(R.layout.api_register_activity); + setContentView(R.layout.api_app_settings_activity); LinearLayout layoutRegister = (LinearLayout) findViewById(R.id.register_crypto_consumer_register_layout); LinearLayout layoutEdit = (LinearLayout) findViewById(R.id.register_crypto_consumer_edit_layout); -- cgit v1.2.3 From fcec7e830c11fa0bda903ea9913fa2e41fa4d2e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 4 Sep 2013 23:47:40 +0200 Subject: App settings activity --- .../keychain/provider/KeychainProvider.java | 7 +++ .../keychain/remote_api/AppSettingsActivity.java | 63 +++++++++++++++++++-- .../keychain/remote_api/AppSettingsFragment.java | 66 +++++++++++++++++++++- .../keychain/remote_api/RegisteredAppsAdapter.java | 5 +- .../remote_api/RegisteredAppsListFragment.java | 2 +- .../keychain/ui/SelectPublicKeyFragment.java | 13 +++-- .../keychain/ui/SelectSecretKeyFragment.java | 2 +- .../keychain/ui/widget/ImportKeysListLoader.java | 10 ---- .../keychain/ui/widget/SelectKeyCursorAdapter.java | 12 ++-- 9 files changed, 147 insertions(+), 33 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 5a86b0bdb..c875b7a70 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -611,6 +611,13 @@ public class KeychainProvider extends ContentProvider { case CRYPTO_CONSUMERS: qb.setTables(Tables.CRYPTO_CONSUMERS); + break; + case CRYPTO_CONSUMERS_BY_ROW_ID: + qb.setTables(Tables.CRYPTO_CONSUMERS); + + qb.appendWhere(BaseColumns._ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); + break; case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: qb.setTables(Tables.CRYPTO_CONSUMERS); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 31fbdc8a6..765cb8e2b 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -2,34 +2,89 @@ package org.sufficientlysecure.keychain.remote_api; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; +import android.content.ContentUris; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragmentActivity; public class AppSettingsActivity extends SherlockFragmentActivity { + private PackageManager pm; + + long id; + + String packageName; + long keyId; + boolean asciiArmor; + + // derived + String appName; + + // view + TextView selectedKey; + Button selectKeyButton; + CheckBox asciiArmorCheckBox; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + pm = getApplicationContext().getPackageManager(); + setContentView(R.layout.api_app_settings_activity); - // check if add new or edit existing + selectedKey = (TextView) findViewById(R.id.api_app_settings_selected_key); + selectKeyButton = (Button) findViewById(R.id.api_app_settings_select_key_button); + asciiArmorCheckBox = (CheckBox) findViewById(R.id.api_app_ascii_armor); + Intent intent = getIntent(); Uri appUri = intent.getData(); if (appUri == null) { Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); finish(); return; + } else { + Log.d(Constants.TAG, "uri: " + appUri); + loadData(appUri); + } + } + + private void loadData(Uri appUri) { + Cursor cur = getContentResolver().query(appUri, null, null, null, null); + id = ContentUris.parseId(appUri); + if (cur.moveToFirst()) { + do { + packageName = cur.getString(cur + .getColumnIndex(KeychainContract.CryptoConsumers.PACKAGE_NAME)); + // get application name + try { + ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); + + appName = (String) pm.getApplicationLabel(ai); + } catch (final NameNotFoundException e) { + appName = getString(R.string.api_unknown_app); + } +// asciiArmor = (cur.getInt(cur +// .getColumnIndex(KeychainContract.CryptoConsumers.ASCII_ARMOR)) == 1); + + // display values +// asciiArmorCheckBox.setChecked(asciiArmor); + + } while (cur.moveToNext()); } - Log.d(Constants.TAG, "uri: " + appUri); - - } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java index 4bb09d50f..98cf5abd5 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -1,15 +1,28 @@ package org.sufficientlysecure.keychain.remote_api; +import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity; +import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.Button; +import android.widget.LinearLayout; public class AppSettingsFragment extends Fragment { - + + private LinearLayout advancedSettingsContainer; + private Button advancedSettingsButton; + + private Button selectKeyButton; + /** * Inflate the layout for this fragment */ @@ -17,4 +30,55 @@ public class AppSettingsFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.api_app_settings_fragment, container, false); } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + advancedSettingsButton = (Button) getActivity().findViewById( + R.id.api_app_settings_advanced_button); + advancedSettingsContainer = (LinearLayout) getActivity().findViewById( + R.id.api_app_settings_advanced); + selectKeyButton = (Button) getActivity().findViewById( + R.id.api_app_settings_select_key_button); + + final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f); + visibleAnimation.setDuration(250); + final Animation invisibleAnimation = new AlphaAnimation(1.0f, 0.0f); + invisibleAnimation.setDuration(250); + + // TODO: Better: collapse/expand animation + // final Animation animation2 = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, + // Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, + // Animation.RELATIVE_TO_SELF, 0.0f); + // animation2.setDuration(150); + + advancedSettingsButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (advancedSettingsContainer.getVisibility() == View.VISIBLE) { + advancedSettingsContainer.startAnimation(invisibleAnimation); + advancedSettingsContainer.setVisibility(View.INVISIBLE); + } else { + advancedSettingsContainer.startAnimation(visibleAnimation); + advancedSettingsContainer.setVisibility(View.VISIBLE); + } + } + }); + + selectKeyButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + selectSecretKey(); + + } + }); + } + + private void selectSecretKey() { + Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class); + startActivityForResult(intent, Id.request.secret_keys); + } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java index 61888ad5a..dcc0b973d 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java @@ -35,9 +35,8 @@ public class RegisteredAppsAdapter extends CursorAdapter { private LayoutInflater mInflater; private PackageManager pm; - @SuppressWarnings("deprecation") - public RegisteredAppsAdapter(Context context, Cursor c) { - super(context, c); + public RegisteredAppsAdapter(Context context, Cursor c, int flags) { + super(context, c, flags); mInflater = LayoutInflater.from(context); pm = context.getApplicationContext().getPackageManager(); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java index 52f4d1398..bd879a1b6 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java @@ -51,7 +51,7 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements setHasOptionsMenu(true); // Create an empty adapter we will use to display the loaded data. - mAdapter = new RegisteredAppsAdapter(getActivity(), null); + mAdapter = new RegisteredAppsAdapter(getActivity(), null, 0); setListAdapter(mAdapter); // Prepare the loader. Either re-connect with an existing one, diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java index 8b3e75d05..b9c42a17c 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java @@ -67,7 +67,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements // application this would come from a resource. setEmptyText(getString(R.string.listEmpty)); - mAdapter = new SelectKeyCursorAdapter(mActivity, mListView, null, Id.type.public_key); + mAdapter = new SelectKeyCursorAdapter(mActivity, null, 0, mListView, Id.type.public_key); setListAdapter(mAdapter); @@ -160,11 +160,12 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements + SelectKeyCursorAdapter.PROJECTION_ROW_AVAILABLE, "(SELECT COUNT(valid_keys." + Keys._ID + ") FROM " + Tables.KEYS + " AS valid_keys WHERE valid_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND valid_keys." - + Keys.IS_REVOKED + " = '0' AND valid_keys." + Keys.CAN_ENCRYPT - + " = '1' AND valid_keys." + Keys.CREATION + " <= '" + now + "' AND " - + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys." + Keys.EXPIRY - + " >= '" + now + "')) AS " + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; + + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + + " AND valid_keys." + Keys.IS_REVOKED + " = '0' AND valid_keys." + + Keys.CAN_ENCRYPT + " = '1' AND valid_keys." + Keys.CREATION + " <= '" + + now + "' AND " + "(valid_keys." + Keys.EXPIRY + " IS NULL OR valid_keys." + + Keys.EXPIRY + " >= '" + now + "')) AS " + + SelectKeyCursorAdapter.PROJECTION_ROW_VALID, }; String inMasterKeyList = null; if (mSelectedMasterKeyIds != null && mSelectedMasterKeyIds.length > 0) { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java index 4871b74bc..9b87f085c 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java @@ -73,7 +73,7 @@ public class SelectSecretKeyFragment extends SherlockListFragment implements // application this would come from a resource. setEmptyText(getString(R.string.listEmpty)); - mAdapter = new SelectKeyCursorAdapter(mActivity, mListView, null, Id.type.secret_key); + mAdapter = new SelectKeyCursorAdapter(mActivity, null, 0, mListView, Id.type.secret_key); setListAdapter(mAdapter); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java index 198140e0c..94d578384 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java @@ -23,19 +23,14 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPPublicKeyRingCollection; import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSecretKeyRingCollection; import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.helper.PgpConversionHelper; import org.sufficientlysecure.keychain.helper.PgpHelper; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -45,11 +40,6 @@ import org.sufficientlysecure.keychain.R; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; -/** - * A custom Loader to search for bad adware apps, based on - * https://github.com/brosmike/AirPush-Detector. Daniel Bjorge licensed it under Apachev2 after - * asking him by mail. - */ public class ImportKeysListLoader extends AsyncTaskLoader>> { public static final String MAP_ATTR_USER_ID = "user_id"; public static final String MAP_ATTR_FINGERPINT = "fingerprint"; diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java index 17423136f..5d8b7d1b1 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java @@ -44,9 +44,9 @@ public class SelectKeyCursorAdapter extends CursorAdapter { public final static String PROJECTION_ROW_AVAILABLE = "available"; public final static String PROJECTION_ROW_VALID = "valid"; - @SuppressWarnings("deprecation") - public SelectKeyCursorAdapter(Context context, ListView listView, Cursor c, int keyType) { - super(context, c); + public SelectKeyCursorAdapter(Context context, Cursor c, int flags, ListView listView, + int keyType) { + super(context, c, flags); mInflater = LayoutInflater.from(context); mListView = listView; @@ -65,8 +65,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter { @Override public void bindView(View view, Context context, Cursor cursor) { - boolean valid = cursor.getInt(cursor - .getColumnIndex(PROJECTION_ROW_VALID)) > 0; + boolean valid = cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_VALID)) > 0; TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); mainUserId.setText(R.string.unknownUserId); @@ -101,8 +100,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter { status.setText(R.string.canSign); } } else { - if (cursor.getInt(cursor - .getColumnIndex(PROJECTION_ROW_AVAILABLE)) > 0) { + if (cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_AVAILABLE)) > 0) { // has some CAN_ENCRYPT keys, but col(ROW_VALID) = 0, so must be revoked or // expired status.setText(R.string.expired); -- cgit v1.2.3 From 9a737c7318e20a56a7d7a2efd8602fb0bec05101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Sep 2013 00:02:48 +0200 Subject: rename crypto consumers to api apps --- .../keychain/provider/KeychainContract.java | 12 ++--- .../keychain/provider/KeychainDatabase.java | 24 ++++----- .../keychain/provider/KeychainProvider.java | 28 +++++----- .../keychain/provider/ProviderHelper.java | 10 ++-- .../keychain/remote_api/AppSettingsActivity.java | 60 ++++++++++++++++++---- .../keychain/remote_api/AppSettingsFragment.java | 3 +- .../keychain/remote_api/RegisteredAppsAdapter.java | 4 +- .../remote_api/RegisteredAppsListFragment.java | 12 ++--- .../keychain/remote_api/ServiceActivity.java | 36 +++++++------ 9 files changed, 118 insertions(+), 71 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java index 985498e3a..e9637c35d 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -53,7 +53,7 @@ public class KeychainContract { String RANK = "rank"; } - interface CryptoConsumersColumns { + interface ApiAppsColumns { String PACKAGE_NAME = "package_name"; String PRIVATE_KEY_ID = "private_key_id"; // not a database id String ASCII_ARMOR = "ascii_armor"; @@ -87,7 +87,7 @@ public class KeychainContract { public static final String PATH_USER_IDS = "user_ids"; public static final String PATH_KEYS = "keys"; - public static final String BASE_CRYPTO_CONSUMERS = "crypto_consumers"; + public static final String BASE_API_APPS = "api_apps"; public static final String PATH_BY_PACKAGE_NAME = "package_name"; public static class KeyRings implements KeyRingsColumns, BaseColumns { @@ -219,15 +219,15 @@ public class KeychainContract { } } - public static class CryptoConsumers implements CryptoConsumersColumns, BaseColumns { + public static class ApiApps implements ApiAppsColumns, BaseColumns { public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_CRYPTO_CONSUMERS).build(); + .appendPath(BASE_API_APPS).build(); /** Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.crypto_consumers"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_apps"; /** Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.crypto_consumers"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps"; public static Uri buildIdUri(String rowId) { return CONTENT_URI.buildUpon().appendPath(rowId).build(); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 6f31f4945..283ab73e3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -18,7 +18,7 @@ package org.sufficientlysecure.keychain.provider; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumersColumns; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; @@ -37,7 +37,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { String KEY_RINGS = "key_rings"; String KEYS = "keys"; String USER_IDS = "user_ids"; - String CRYPTO_CONSUMERS = "crypto_consumers"; + String API_APPS = "api_apps"; } private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS @@ -64,14 +64,14 @@ public class KeychainDatabase extends SQLiteOpenHelper { + UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)"; - private static final String CREATE_CRYPTO_CONSUMERS = "CREATE TABLE IF NOT EXISTS " - + Tables.CRYPTO_CONSUMERS + " (" + BaseColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT, " + CryptoConsumersColumns.PACKAGE_NAME - + " TEXT UNIQUE, " + CryptoConsumersColumns.PRIVATE_KEY_ID + " INT64, " - + CryptoConsumersColumns.ASCII_ARMOR + " INTEGER, " - + CryptoConsumersColumns.ENCRYPTION_ALGORITHM + " INTEGER, " - + CryptoConsumersColumns.HASH_ALORITHM + " INTEGER, " - + CryptoConsumersColumns.COMPRESSION + " INTEGER)"; + private static final String CREATE_API_APPS = "CREATE TABLE IF NOT EXISTS " + + Tables.API_APPS + " (" + BaseColumns._ID + + " INTEGER PRIMARY KEY AUTOINCREMENT, " + ApiAppsColumns.PACKAGE_NAME + + " TEXT UNIQUE, " + ApiAppsColumns.PRIVATE_KEY_ID + " INT64, " + + ApiAppsColumns.ASCII_ARMOR + " INTEGER, " + + ApiAppsColumns.ENCRYPTION_ALGORITHM + " INTEGER, " + + ApiAppsColumns.HASH_ALORITHM + " INTEGER, " + + ApiAppsColumns.COMPRESSION + " INTEGER)"; KeychainDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); @@ -84,7 +84,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL(CREATE_KEY_RINGS); db.execSQL(CREATE_KEYS); db.execSQL(CREATE_USER_IDS); - db.execSQL(CREATE_CRYPTO_CONSUMERS); + db.execSQL(CREATE_API_APPS); } @Override @@ -112,7 +112,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;"); break; case 4: - db.execSQL(CREATE_CRYPTO_CONSUMERS); + db.execSQL(CREATE_API_APPS); default: break; diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index c875b7a70..6275b3b5c 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.HashMap; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes; @@ -228,10 +228,10 @@ public class KeychainProvider extends ContentProvider { /** * Crypto Consumers */ - matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS, CRYPTO_CONSUMERS); - matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS + "/#", + matcher.addURI(authority, KeychainContract.BASE_API_APPS, CRYPTO_CONSUMERS); + matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", CRYPTO_CONSUMERS_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS + "/" + matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/" + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", CRYPTO_CONSUMERS_BY_PACKAGE_NAME); /** @@ -294,11 +294,11 @@ public class KeychainProvider extends ContentProvider { return UserIds.CONTENT_ITEM_TYPE; case CRYPTO_CONSUMERS: - return CryptoConsumers.CONTENT_TYPE; + return ApiApps.CONTENT_TYPE; case CRYPTO_CONSUMERS_BY_ROW_ID: case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: - return CryptoConsumers.CONTENT_ITEM_TYPE; + return ApiApps.CONTENT_ITEM_TYPE; default: throw new UnsupportedOperationException("Unknown uri: " + uri); @@ -609,19 +609,19 @@ public class KeychainProvider extends ContentProvider { break; case CRYPTO_CONSUMERS: - qb.setTables(Tables.CRYPTO_CONSUMERS); + qb.setTables(Tables.API_APPS); break; case CRYPTO_CONSUMERS_BY_ROW_ID: - qb.setTables(Tables.CRYPTO_CONSUMERS); + qb.setTables(Tables.API_APPS); qb.appendWhere(BaseColumns._ID + " = "); qb.appendWhereEscapeString(uri.getLastPathSegment()); break; case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: - qb.setTables(Tables.CRYPTO_CONSUMERS); - qb.appendWhere(CryptoConsumers.PACKAGE_NAME + " = "); + qb.setTables(Tables.API_APPS); + qb.appendWhere(ApiApps.PACKAGE_NAME + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(2)); break; @@ -712,8 +712,8 @@ public class KeychainProvider extends ContentProvider { break; case CRYPTO_CONSUMERS: - rowId = db.insertOrThrow(Tables.CRYPTO_CONSUMERS, null, values); - rowUri = CryptoConsumers.buildIdUri(Long.toString(rowId)); + rowId = db.insertOrThrow(Tables.API_APPS, null, values); + rowUri = ApiApps.buildIdUri(Long.toString(rowId)); break; default: @@ -773,7 +773,7 @@ public class KeychainProvider extends ContentProvider { break; case CRYPTO_CONSUMERS_BY_ROW_ID: case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: - count = db.delete(Tables.CRYPTO_CONSUMERS, + count = db.delete(Tables.API_APPS, buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); break; default: @@ -838,7 +838,7 @@ public class KeychainProvider extends ContentProvider { break; case CRYPTO_CONSUMERS_BY_ROW_ID: case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: - count = db.update(Tables.CRYPTO_CONSUMERS, values, + count = db.update(Tables.API_APPS, values, buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); break; default: diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 57d3b54d6..c8f9baeff 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -31,7 +31,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.helper.PgpConversionHelper; import org.sufficientlysecure.keychain.helper.PgpHelper; import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; @@ -719,12 +719,12 @@ public class ProviderHelper { } public static ArrayList getCryptoConsumers(Context context) { - Cursor cursor = context.getContentResolver().query(CryptoConsumers.CONTENT_URI, null, null, + Cursor cursor = context.getContentResolver().query(ApiApps.CONTENT_URI, null, null, null, null); ArrayList packageNames = new ArrayList(); if (cursor != null) { - int packageNameCol = cursor.getColumnIndex(CryptoConsumers.PACKAGE_NAME); + int packageNameCol = cursor.getColumnIndex(ApiApps.PACKAGE_NAME); if (cursor.moveToFirst()) { do { packageNames.add(cursor.getString(packageNameCol)); @@ -741,7 +741,7 @@ public class ProviderHelper { public static void addCryptoConsumer(Context context, String packageName) { ContentValues values = new ContentValues(); - values.put(CryptoConsumers.PACKAGE_NAME, packageName); - context.getContentResolver().insert(CryptoConsumers.CONTENT_URI, values); + values.put(ApiApps.PACKAGE_NAME, packageName); + context.getContentResolver().insert(ApiApps.CONTENT_URI, values); } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 765cb8e2b..3046dd0d2 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -6,6 +6,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; import android.content.ContentUris; +import android.content.ContentValues; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -13,6 +14,8 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; @@ -20,22 +23,24 @@ import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragmentActivity; public class AppSettingsActivity extends SherlockFragmentActivity { - private PackageManager pm; + // model + Uri appUri; long id; - String packageName; long keyId; boolean asciiArmor; - // derived + // model, derived String appName; // view TextView selectedKey; Button selectKeyButton; CheckBox asciiArmorCheckBox; + Button saveButton; + Button revokeButton; @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,9 +53,26 @@ public class AppSettingsActivity extends SherlockFragmentActivity { selectedKey = (TextView) findViewById(R.id.api_app_settings_selected_key); selectKeyButton = (Button) findViewById(R.id.api_app_settings_select_key_button); asciiArmorCheckBox = (CheckBox) findViewById(R.id.api_app_ascii_armor); + revokeButton = (Button) findViewById(R.id.api_app_settings_revoke); + saveButton = (Button) findViewById(R.id.api_app_settings_save); + + revokeButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + revokeAccess(); + } + }); + saveButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + save(); + } + }); Intent intent = getIntent(); - Uri appUri = intent.getData(); + appUri = intent.getData(); if (appUri == null) { Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); finish(); @@ -67,7 +89,7 @@ public class AppSettingsActivity extends SherlockFragmentActivity { if (cur.moveToFirst()) { do { packageName = cur.getString(cur - .getColumnIndex(KeychainContract.CryptoConsumers.PACKAGE_NAME)); + .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); // get application name try { ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); @@ -76,15 +98,35 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } catch (final NameNotFoundException e) { appName = getString(R.string.api_unknown_app); } -// asciiArmor = (cur.getInt(cur -// .getColumnIndex(KeychainContract.CryptoConsumers.ASCII_ARMOR)) == 1); - // display values -// asciiArmorCheckBox.setChecked(asciiArmor); + try { + asciiArmor = (cur.getInt(cur + .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); + + // display values + asciiArmorCheckBox.setChecked(asciiArmor); + } catch (IllegalArgumentException e) { + Log.e(Constants.TAG, "AppSettingsActivity", e); + } } while (cur.moveToNext()); } + } + + private void revokeAccess() { + Uri calUri = ContentUris.withAppendedId(appUri, id); + getContentResolver().delete(calUri, null, null); + finish(); + } + + private void save() { + final ContentValues cv = new ContentValues(); + cv.put(KeychainContract.ApiApps.PACKAGE_NAME, packageName); + cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmor); + // TODO: other parameter + getContentResolver().update(appUri, cv, null, null); + finish(); } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java index 98cf5abd5..ec983dc06 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -60,9 +60,11 @@ public class AppSettingsFragment extends Fragment { if (advancedSettingsContainer.getVisibility() == View.VISIBLE) { advancedSettingsContainer.startAnimation(invisibleAnimation); advancedSettingsContainer.setVisibility(View.INVISIBLE); + advancedSettingsButton.setText(R.string.api_settings_show_advanced); } else { advancedSettingsContainer.startAnimation(visibleAnimation); advancedSettingsContainer.setVisibility(View.VISIBLE); + advancedSettingsButton.setText(R.string.api_settings_hide_advanced); } } }); @@ -72,7 +74,6 @@ public class AppSettingsFragment extends Fragment { @Override public void onClick(View v) { selectSecretKey(); - } }); } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java index dcc0b973d..71a819ec2 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java @@ -17,7 +17,7 @@ package org.sufficientlysecure.keychain.remote_api; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -47,7 +47,7 @@ public class RegisteredAppsAdapter extends CursorAdapter { TextView text1 = (TextView) view.findViewById(android.R.id.text1); TextView text2 = (TextView) view.findViewById(android.R.id.text2); - String packageName = cursor.getString(cursor.getColumnIndex(CryptoConsumers.PACKAGE_NAME)); + String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME)); if (packageName != null) { text2.setText(packageName); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java index bd879a1b6..5ab210d5f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java @@ -2,7 +2,7 @@ package org.sufficientlysecure.keychain.remote_api; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers; +import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import com.actionbarsherlock.app.SherlockListFragment; @@ -38,7 +38,7 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements // edit app settings Intent intent = new Intent(getActivity(), AppSettingsActivity.class); intent.setData(ContentUris.withAppendedId( - KeychainContract.CryptoConsumers.CONTENT_URI, id)); + KeychainContract.ApiApps.CONTENT_URI, id)); startActivity(intent); } }); @@ -60,20 +60,20 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements } // These are the Contacts rows that we will retrieve. - static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { CryptoConsumers._ID, - CryptoConsumers.PACKAGE_NAME }; + static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { ApiApps._ID, + ApiApps.PACKAGE_NAME }; public Loader onCreateLoader(int id, Bundle args) { // 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. // First, pick the base URI to use depending on whether we are // currently filtering. - Uri baseUri = CryptoConsumers.CONTENT_URI; + Uri baseUri = ApiApps.CONTENT_URI; // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null, - CryptoConsumers.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); + ApiApps.PACKAGE_NAME + " COLLATE LOCALIZED ASC"); } public void onLoadFinished(Loader loader, Cursor data) { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 5849fb80d..703093f0a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -134,22 +134,26 @@ public class ServiceActivity extends SherlockFragmentActivity { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); setContentView(R.layout.api_app_settings_activity); - LinearLayout layoutRegister = (LinearLayout) findViewById(R.id.register_crypto_consumer_register_layout); - LinearLayout layoutEdit = (LinearLayout) findViewById(R.id.register_crypto_consumer_edit_layout); - - // if already registered show edit buttons - ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(this); - if (allowedPkgs.contains(packageName)) { - Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); - layoutRegister.setVisibility(View.GONE); - layoutEdit.setVisibility(View.VISIBLE); - } else { - layoutRegister.setVisibility(View.VISIBLE); - layoutEdit.setVisibility(View.GONE); - } - - Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow); - Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow); + + //TODO: handle if app is already registered + // LinearLayout layoutRegister = (LinearLayout) + // findViewById(R.id.register_crypto_consumer_register_layout); + // LinearLayout layoutEdit = (LinearLayout) + // findViewById(R.id.register_crypto_consumer_edit_layout); + // + // // if already registered show edit buttons + // ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(this); + // if (allowedPkgs.contains(packageName)) { + // Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + // layoutRegister.setVisibility(View.GONE); + // layoutEdit.setVisibility(View.VISIBLE); + // } else { + // layoutRegister.setVisibility(View.VISIBLE); + // layoutEdit.setVisibility(View.GONE); + // } + + Button allowButton = (Button) findViewById(R.id.api_register_allow); + Button disallowButton = (Button) findViewById(R.id.api_register_disallow); allowButton.setOnClickListener(new OnClickListener() { -- cgit v1.2.3 From 8614ff2ec74447f7199a5822f9331a0991161038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Sep 2013 00:27:17 +0200 Subject: Fix revoke and save --- .../keychain/provider/KeychainProvider.java | 63 +++++++++++++--------- .../keychain/remote_api/AppSettingsActivity.java | 61 ++++++++++----------- .../keychain/remote_api/ServiceActivity.java | 6 +-- 3 files changed, 69 insertions(+), 61 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 6275b3b5c..98a45d69f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -78,9 +78,9 @@ public class KeychainProvider extends ContentProvider { private static final int SECRET_KEY_RING_USER_ID = 221; private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222; - private static final int CRYPTO_CONSUMERS = 301; - private static final int CRYPTO_CONSUMERS_BY_ROW_ID = 302; - private static final int CRYPTO_CONSUMERS_BY_PACKAGE_NAME = 303; + private static final int API_APPS = 301; + private static final int API_APPS_BY_ROW_ID = 302; + private static final int API_APPS_BY_PACKAGE_NAME = 303; // private static final int DATA_STREAM = 401; @@ -226,13 +226,12 @@ public class KeychainProvider extends ContentProvider { SECRET_KEY_RING_USER_ID_BY_ROW_ID); /** - * Crypto Consumers + * API apps */ - matcher.addURI(authority, KeychainContract.BASE_API_APPS, CRYPTO_CONSUMERS); - matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", - CRYPTO_CONSUMERS_BY_ROW_ID); + matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS); + matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", API_APPS_BY_ROW_ID); matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/" - + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", CRYPTO_CONSUMERS_BY_PACKAGE_NAME); + + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME); /** * data stream @@ -293,11 +292,11 @@ public class KeychainProvider extends ContentProvider { case SECRET_KEY_RING_USER_ID_BY_ROW_ID: return UserIds.CONTENT_ITEM_TYPE; - case CRYPTO_CONSUMERS: + case API_APPS: return ApiApps.CONTENT_TYPE; - case CRYPTO_CONSUMERS_BY_ROW_ID: - case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: + case API_APPS_BY_ROW_ID: + case API_APPS_BY_PACKAGE_NAME: return ApiApps.CONTENT_ITEM_TYPE; default: @@ -608,18 +607,18 @@ public class KeychainProvider extends ContentProvider { break; - case CRYPTO_CONSUMERS: + case API_APPS: qb.setTables(Tables.API_APPS); break; - case CRYPTO_CONSUMERS_BY_ROW_ID: + case API_APPS_BY_ROW_ID: qb.setTables(Tables.API_APPS); qb.appendWhere(BaseColumns._ID + " = "); qb.appendWhereEscapeString(uri.getLastPathSegment()); break; - case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: + case API_APPS_BY_PACKAGE_NAME: qb.setTables(Tables.API_APPS); qb.appendWhere(ApiApps.PACKAGE_NAME + " = "); qb.appendWhereEscapeString(uri.getPathSegments().get(2)); @@ -711,7 +710,7 @@ public class KeychainProvider extends ContentProvider { rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId)); break; - case CRYPTO_CONSUMERS: + case API_APPS: rowId = db.insertOrThrow(Tables.API_APPS, null, values); rowUri = ApiApps.buildIdUri(Long.toString(rowId)); @@ -771,10 +770,13 @@ public class KeychainProvider extends ContentProvider { count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection), selectionArgs); break; - case CRYPTO_CONSUMERS_BY_ROW_ID: - case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: - count = db.delete(Tables.API_APPS, - buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); + case API_APPS_BY_ROW_ID: + count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, false, selection), + selectionArgs); + break; + case API_APPS_BY_PACKAGE_NAME: + count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, true, selection), + selectionArgs); break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); @@ -836,10 +838,13 @@ public class KeychainProvider extends ContentProvider { count = db.update(Tables.USER_IDS, values, buildDefaultUserIdsSelection(uri, selection), selectionArgs); break; - case CRYPTO_CONSUMERS_BY_ROW_ID: - case CRYPTO_CONSUMERS_BY_PACKAGE_NAME: + case API_APPS_BY_ROW_ID: + count = db.update(Tables.API_APPS, values, + buildDefaultApiAppsSelection(uri, false, selection), selectionArgs); + break; + case API_APPS_BY_PACKAGE_NAME: count = db.update(Tables.API_APPS, values, - buildDefaultCryptoConsumersSelection(uri, selection), selectionArgs); + buildDefaultApiAppsSelection(uri, true, selection), selectionArgs); break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); @@ -930,20 +935,26 @@ public class KeychainProvider extends ContentProvider { } /** - * Build default selection statement for Crypto Consumers. If no extra selection is specified - * only build where clause with rowId + * Build default selection statement for API apps. If no extra selection is specified only build + * where clause with rowId * * @param uri * @param selection * @return */ - private String buildDefaultCryptoConsumersSelection(Uri uri, String selection) { + private String buildDefaultApiAppsSelection(Uri uri, boolean packageSelection, String selection) { + String lastPathSegment = uri.getLastPathSegment(); + String andSelection = ""; if (!TextUtils.isEmpty(selection)) { andSelection = " AND (" + selection + ")"; } - return selection + andSelection; + if (packageSelection) { + return ApiApps.PACKAGE_NAME + "=" + lastPathSegment + andSelection; + } else { + return BaseColumns._ID + "=" + lastPathSegment + andSelection; + } } // @Override diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 3046dd0d2..6316dbc38 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -27,10 +27,8 @@ public class AppSettingsActivity extends SherlockFragmentActivity { // model Uri appUri; - long id; String packageName; long keyId; - boolean asciiArmor; // model, derived String appName; @@ -85,46 +83,45 @@ public class AppSettingsActivity extends SherlockFragmentActivity { private void loadData(Uri appUri) { Cursor cur = getContentResolver().query(appUri, null, null, null, null); - id = ContentUris.parseId(appUri); if (cur.moveToFirst()) { - do { - packageName = cur.getString(cur - .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); - // get application name - try { - ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - - appName = (String) pm.getApplicationLabel(ai); - } catch (final NameNotFoundException e) { - appName = getString(R.string.api_unknown_app); - } - - try { - asciiArmor = (cur.getInt(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); - - // display values - asciiArmorCheckBox.setChecked(asciiArmor); - } catch (IllegalArgumentException e) { - Log.e(Constants.TAG, "AppSettingsActivity", e); - } - - } while (cur.moveToNext()); + packageName = cur.getString(cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); + // get application name + try { + ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); + + appName = (String) pm.getApplicationLabel(ai); + } catch (final NameNotFoundException e) { + appName = getString(R.string.api_unknown_app); + } + setTitle(appName); + + try { + boolean asciiArmor = (cur.getInt(cur + .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); + asciiArmorCheckBox.setChecked(asciiArmor); + + } catch (IllegalArgumentException e) { + Log.e(Constants.TAG, "AppSettingsActivity", e); + } } } private void revokeAccess() { - Uri calUri = ContentUris.withAppendedId(appUri, id); - getContentResolver().delete(calUri, null, null); + if (getContentResolver().delete(appUri, null, null) <= 0) { + throw new RuntimeException(); + } finish(); } private void save() { + Log.d(Constants.TAG, "saving"); final ContentValues cv = new ContentValues(); - cv.put(KeychainContract.ApiApps.PACKAGE_NAME, packageName); - cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmor); - // TODO: other parameter - getContentResolver().update(appUri, cv, null, null); + // cv.put(KeychainContract.ApiApps.PACKAGE_NAME, packageName); + cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmorCheckBox.isChecked()); + // TODO: other parameters + if (getContentResolver().update(appUri, cv, null, null) <= 0) { + throw new RuntimeException(); + } finish(); } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 703093f0a..00bba7757 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -133,9 +133,9 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - setContentView(R.layout.api_app_settings_activity); - - //TODO: handle if app is already registered + setContentView(R.layout.api_app_register_activity); + + // TODO: handle if app is already registered // LinearLayout layoutRegister = (LinearLayout) // findViewById(R.id.register_crypto_consumer_register_layout); // LinearLayout layoutEdit = (LinearLayout) -- cgit v1.2.3 From 00d03d452ecde61cd6fe29eeadbf7a3d2e9050e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Sep 2013 21:25:49 +0200 Subject: Include DoneBar for edit activities --- .../keychain/remote_api/AppSettingsActivity.java | 69 +++++++++++++++------- 1 file changed, 49 insertions(+), 20 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 6316dbc38..0cfbbe3fc 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -5,7 +5,6 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; -import android.content.ContentUris; import android.content.ContentValues; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -14,13 +13,16 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; +import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; public class AppSettingsActivity extends SherlockFragmentActivity { private PackageManager pm; @@ -46,28 +48,36 @@ public class AppSettingsActivity extends SherlockFragmentActivity { pm = getApplicationContext().getPackageManager(); + // BEGIN_INCLUDE (inflate_set_custom_view) + // Inflate a "Done" custom action bar view to serve as the "Up" affordance. + final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext() + .getSystemService(LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater + .inflate(R.layout.actionbar_custom_view_done, null); + + ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)) + .setText(R.string.api_settings_save); + customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // "Done" + save(); + } + }); + + // Show the custom action bar view and hide the normal Home icon and title. + final ActionBar actionBar = getSupportActionBar(); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM + | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE); + actionBar.setCustomView(customActionBarView); + // END_INCLUDE (inflate_set_custom_view) + setContentView(R.layout.api_app_settings_activity); selectedKey = (TextView) findViewById(R.id.api_app_settings_selected_key); selectKeyButton = (Button) findViewById(R.id.api_app_settings_select_key_button); asciiArmorCheckBox = (CheckBox) findViewById(R.id.api_app_ascii_armor); - revokeButton = (Button) findViewById(R.id.api_app_settings_revoke); - saveButton = (Button) findViewById(R.id.api_app_settings_save); - - revokeButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - revokeAccess(); - } - }); - saveButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - save(); - } - }); Intent intent = getIntent(); appUri = intent.getData(); @@ -81,6 +91,26 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + getSupportMenuInflater().inflate(R.menu.api_app_settings, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_api_settings_revoke: + revokeAccess(); + return true; + case R.id.menu_api_settings_cancel: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + private void loadData(Uri appUri) { Cursor cur = getContentResolver().query(appUri, null, null, null, null); if (cur.moveToFirst()) { @@ -114,7 +144,6 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } private void save() { - Log.d(Constants.TAG, "saving"); final ContentValues cv = new ContentValues(); // cv.put(KeychainContract.ApiApps.PACKAGE_NAME, packageName); cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmorCheckBox.isChecked()); -- cgit v1.2.3 From 2b303d35583a31dfa994ca722f98446a474eb5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 08:29:56 +0200 Subject: select key for api apps --- .../keychain/provider/KeychainContract.java | 2 +- .../keychain/provider/KeychainDatabase.java | 2 +- .../keychain/remote_api/AppSettingsActivity.java | 123 +++++++++++++++++---- .../keychain/remote_api/AppSettingsFragment.java | 16 --- 4 files changed, 106 insertions(+), 37 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java index e9637c35d..93ee50a5e 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -55,7 +55,7 @@ public class KeychainContract { interface ApiAppsColumns { String PACKAGE_NAME = "package_name"; - String PRIVATE_KEY_ID = "private_key_id"; // not a database id + String KEY_ID = "key_id"; // not a database id String ASCII_ARMOR = "ascii_armor"; String ENCRYPTION_ALGORITHM = "encryption_algorithm"; String HASH_ALORITHM = "hash_algorithm"; diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 283ab73e3..6da96f45f 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -67,7 +67,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { private static final String CREATE_API_APPS = "CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + ApiAppsColumns.PACKAGE_NAME - + " TEXT UNIQUE, " + ApiAppsColumns.PRIVATE_KEY_ID + " INT64, " + + " TEXT UNIQUE, " + ApiAppsColumns.KEY_ID + " INT64, " + ApiAppsColumns.ASCII_ARMOR + " INTEGER, " + ApiAppsColumns.ENCRYPTION_ALGORITHM + " INTEGER, " + ApiAppsColumns.HASH_ALORITHM + " INTEGER, " diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 0cfbbe3fc..8d32dd3f5 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -1,8 +1,14 @@ package org.sufficientlysecure.keychain.remote_api; +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.PgpHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity; import org.sufficientlysecure.keychain.util.Log; import android.content.ContentValues; @@ -11,12 +17,15 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; +import android.widget.ImageView; import android.widget.TextView; import com.actionbarsherlock.app.ActionBar; @@ -28,15 +37,15 @@ public class AppSettingsActivity extends SherlockFragmentActivity { private PackageManager pm; // model - Uri appUri; - String packageName; - long keyId; - - // model, derived - String appName; + Uri mAppUri; + String mPackageName; + long mSecretKeyId = Id.key.none; // view - TextView selectedKey; + TextView appNameView; + ImageView appIconView; + TextView keyUserId; + TextView keyUserIdRest; Button selectKeyButton; CheckBox asciiArmorCheckBox; Button saveButton; @@ -75,19 +84,30 @@ public class AppSettingsActivity extends SherlockFragmentActivity { setContentView(R.layout.api_app_settings_activity); - selectedKey = (TextView) findViewById(R.id.api_app_settings_selected_key); + appNameView = (TextView) findViewById(R.id.api_app_settings_app_name); + appIconView = (ImageView) findViewById(R.id.api_app_settings_app_icon); + keyUserId = (TextView) findViewById(R.id.api_app_settings_user_id); + keyUserIdRest = (TextView) findViewById(R.id.api_app_settings_user_id_rest); selectKeyButton = (Button) findViewById(R.id.api_app_settings_select_key_button); asciiArmorCheckBox = (CheckBox) findViewById(R.id.api_app_ascii_armor); + selectKeyButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + selectSecretKey(); + } + }); + Intent intent = getIntent(); - appUri = intent.getData(); - if (appUri == null) { + mAppUri = intent.getData(); + if (mAppUri == null) { Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); finish(); return; } else { - Log.d(Constants.TAG, "uri: " + appUri); - loadData(appUri); + Log.d(Constants.TAG, "uri: " + mAppUri); + loadData(mAppUri); } } @@ -114,18 +134,28 @@ public class AppSettingsActivity extends SherlockFragmentActivity { private void loadData(Uri appUri) { Cursor cur = getContentResolver().query(appUri, null, null, null, null); if (cur.moveToFirst()) { - packageName = cur.getString(cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); - // get application name + mPackageName = cur.getString(cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); + + // get application name and icon from package manager + String appName = null; + Drawable appIcon = null; try { - ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); + ApplicationInfo ai = pm.getApplicationInfo(mPackageName, 0); appName = (String) pm.getApplicationLabel(ai); + appIcon = pm.getApplicationIcon(ai); } catch (final NameNotFoundException e) { appName = getString(R.string.api_unknown_app); } - setTitle(appName); + appNameView.setText(appName); + appIconView.setImageDrawable(appIcon); try { + mSecretKeyId = (cur.getLong(cur + .getColumnIndexOrThrow(KeychainContract.ApiApps.KEY_ID))); + Log.d(Constants.TAG, "mSecretKeyId: " + mSecretKeyId); + updateSelectedKeyView(mSecretKeyId); + boolean asciiArmor = (cur.getInt(cur .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); asciiArmorCheckBox.setChecked(asciiArmor); @@ -137,7 +167,7 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } private void revokeAccess() { - if (getContentResolver().delete(appUri, null, null) <= 0) { + if (getContentResolver().delete(mAppUri, null, null) <= 0) { throw new RuntimeException(); } finish(); @@ -145,14 +175,69 @@ public class AppSettingsActivity extends SherlockFragmentActivity { private void save() { final ContentValues cv = new ContentValues(); - // cv.put(KeychainContract.ApiApps.PACKAGE_NAME, packageName); + cv.put(KeychainContract.ApiApps.KEY_ID, mSecretKeyId); + cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmorCheckBox.isChecked()); // TODO: other parameters - if (getContentResolver().update(appUri, cv, null, null) <= 0) { + + if (getContentResolver().update(mAppUri, cv, null, null) <= 0) { throw new RuntimeException(); } finish(); } + private void selectSecretKey() { + Intent intent = new Intent(this, SelectSecretKeyActivity.class); + startActivityForResult(intent, Id.request.secret_keys); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + + case Id.request.secret_keys: { + if (resultCode == RESULT_OK) { + Bundle bundle = data.getExtras(); + mSecretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID); + } else { + mSecretKeyId = Id.key.none; + } + updateSelectedKeyView(mSecretKeyId); + break; + } + + default: { + break; + } + } + + super.onActivityResult(requestCode, resultCode, data); + } + + private void updateSelectedKeyView(long secretKeyId) { + if (secretKeyId == Id.key.none) { + keyUserId.setText(R.string.api_settings_no_key); + keyUserIdRest.setText(""); + } else { + String uid = getResources().getString(R.string.unknownUserId); + String uidExtra = ""; + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, + secretKeyId); + if (keyRing != null) { + PGPSecretKey key = PgpHelper.getMasterKey(keyRing); + if (key != null) { + String userId = PgpHelper.getMainUserIdSafe(this, key); + String chunks[] = userId.split(" <", 2); + uid = chunks[0]; + if (chunks.length > 1) { + uidExtra = "<" + chunks[1]; + } + } + } + keyUserId.setText(uid); + keyUserIdRest.setText(uidExtra); + } + } + } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java index ec983dc06..46cea389a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -21,8 +21,6 @@ public class AppSettingsFragment extends Fragment { private LinearLayout advancedSettingsContainer; private Button advancedSettingsButton; - private Button selectKeyButton; - /** * Inflate the layout for this fragment */ @@ -39,8 +37,6 @@ public class AppSettingsFragment extends Fragment { R.id.api_app_settings_advanced_button); advancedSettingsContainer = (LinearLayout) getActivity().findViewById( R.id.api_app_settings_advanced); - selectKeyButton = (Button) getActivity().findViewById( - R.id.api_app_settings_select_key_button); final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f); visibleAnimation.setDuration(250); @@ -68,18 +64,6 @@ public class AppSettingsFragment extends Fragment { } } }); - - selectKeyButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - selectSecretKey(); - } - }); } - private void selectSecretKey() { - Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class); - startActivityForResult(intent, Id.request.secret_keys); - } } -- cgit v1.2.3 From 4030739a99a2e1ce232c6c3ab92ab21ad5bc3b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 08:40:13 +0200 Subject: api apps adapter with icons --- .../keychain/remote_api/AppSettingsActivity.java | 3 ++- .../keychain/remote_api/RegisteredAppsAdapter.java | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 8d32dd3f5..44212b5b3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -145,7 +145,8 @@ public class AppSettingsActivity extends SherlockFragmentActivity { appName = (String) pm.getApplicationLabel(ai); appIcon = pm.getApplicationIcon(ai); } catch (final NameNotFoundException e) { - appName = getString(R.string.api_unknown_app); + // fallback + appName = mPackageName; } appNameView.setText(appName); appIconView.setImageDrawable(appIcon); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java index 71a819ec2..9bf66a90a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsAdapter.java @@ -28,6 +28,7 @@ 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; public class RegisteredAppsAdapter extends CursorAdapter { @@ -44,28 +45,31 @@ public class RegisteredAppsAdapter extends CursorAdapter { @Override public void bindView(View view, Context context, Cursor cursor) { - TextView text1 = (TextView) view.findViewById(android.R.id.text1); - TextView text2 = (TextView) view.findViewById(android.R.id.text2); + TextView text = (TextView) view.findViewById(R.id.api_apps_adapter_item_name); + ImageView icon = (ImageView) view.findViewById(R.id.api_apps_adapter_item_icon); String packageName = cursor.getString(cursor.getColumnIndex(ApiApps.PACKAGE_NAME)); if (packageName != null) { - text2.setText(packageName); - // get application name try { ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - text1.setText(pm.getApplicationLabel(ai)); + text.setText(pm.getApplicationLabel(ai)); + icon.setImageDrawable(pm.getApplicationIcon(ai)); } catch (final NameNotFoundException e) { - text1.setText(R.string.api_unknown_app); + // fallback + text.setText(packageName); } + } else { + // fallback + text.setText(packageName); } } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - return mInflater.inflate(android.R.layout.simple_list_item_2, null); + return mInflater.inflate(R.layout.api_apps_adapter_list_item, null); } } -- cgit v1.2.3 From c9549befb250826912d153d40c459fc495aa7fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 09:44:56 +0200 Subject: Put logic into fragment for reuse --- .../keychain/remote_api/AppSettingsActivity.java | 122 ++------------- .../keychain/remote_api/AppSettingsFragment.java | 171 ++++++++++++++++++--- .../keychain/remote_api/ServiceActivity.java | 95 +++++++----- 3 files changed, 224 insertions(+), 164 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 44212b5b3..4e069f3b0 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -1,31 +1,18 @@ package org.sufficientlysecure.keychain.remote_api; -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.PgpHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity; import org.sufficientlysecure.keychain.util.Log; import android.content.ContentValues; import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.widget.Button; -import android.widget.CheckBox; -import android.widget.ImageView; import android.widget.TextView; import com.actionbarsherlock.app.ActionBar; @@ -34,28 +21,21 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; public class AppSettingsActivity extends SherlockFragmentActivity { - private PackageManager pm; - // model Uri mAppUri; String mPackageName; - long mSecretKeyId = Id.key.none; // view - TextView appNameView; - ImageView appIconView; - TextView keyUserId; - TextView keyUserIdRest; - Button selectKeyButton; - CheckBox asciiArmorCheckBox; Button saveButton; Button revokeButton; + AppSettingsFragment settingsFragment; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - pm = getApplicationContext().getPackageManager(); + // pm = getApplicationContext().getPackageManager(); // BEGIN_INCLUDE (inflate_set_custom_view) // Inflate a "Done" custom action bar view to serve as the "Up" affordance. @@ -84,20 +64,8 @@ public class AppSettingsActivity extends SherlockFragmentActivity { setContentView(R.layout.api_app_settings_activity); - appNameView = (TextView) findViewById(R.id.api_app_settings_app_name); - appIconView = (ImageView) findViewById(R.id.api_app_settings_app_icon); - keyUserId = (TextView) findViewById(R.id.api_app_settings_user_id); - keyUserIdRest = (TextView) findViewById(R.id.api_app_settings_user_id_rest); - selectKeyButton = (Button) findViewById(R.id.api_app_settings_select_key_button); - asciiArmorCheckBox = (CheckBox) findViewById(R.id.api_app_ascii_armor); - - selectKeyButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - selectSecretKey(); - } - }); + settingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( + R.id.api_app_settings_fragment); Intent intent = getIntent(); mAppUri = intent.getData(); @@ -136,30 +104,17 @@ public class AppSettingsActivity extends SherlockFragmentActivity { if (cur.moveToFirst()) { mPackageName = cur.getString(cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); - // get application name and icon from package manager - String appName = null; - Drawable appIcon = null; - try { - ApplicationInfo ai = pm.getApplicationInfo(mPackageName, 0); - - appName = (String) pm.getApplicationLabel(ai); - appIcon = pm.getApplicationIcon(ai); - } catch (final NameNotFoundException e) { - // fallback - appName = mPackageName; - } - appNameView.setText(appName); - appIconView.setImageDrawable(appIcon); + settingsFragment.setPackage(mPackageName); try { - mSecretKeyId = (cur.getLong(cur + long secretKeyId = (cur.getLong(cur .getColumnIndexOrThrow(KeychainContract.ApiApps.KEY_ID))); - Log.d(Constants.TAG, "mSecretKeyId: " + mSecretKeyId); - updateSelectedKeyView(mSecretKeyId); + Log.d(Constants.TAG, "mSecretKeyId: " + secretKeyId); + settingsFragment.setSecretKey(secretKeyId); boolean asciiArmor = (cur.getInt(cur .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); - asciiArmorCheckBox.setChecked(asciiArmor); + settingsFragment.setAsciiArmor(asciiArmor); } catch (IllegalArgumentException e) { Log.e(Constants.TAG, "AppSettingsActivity", e); @@ -176,9 +131,9 @@ public class AppSettingsActivity extends SherlockFragmentActivity { private void save() { final ContentValues cv = new ContentValues(); - cv.put(KeychainContract.ApiApps.KEY_ID, mSecretKeyId); + cv.put(KeychainContract.ApiApps.KEY_ID, settingsFragment.getSecretKeyId()); - cv.put(KeychainContract.ApiApps.ASCII_ARMOR, asciiArmorCheckBox.isChecked()); + cv.put(KeychainContract.ApiApps.ASCII_ARMOR, settingsFragment.isAsciiArmor()); // TODO: other parameters if (getContentResolver().update(mAppUri, cv, null, null) <= 0) { @@ -188,57 +143,4 @@ public class AppSettingsActivity extends SherlockFragmentActivity { finish(); } - private void selectSecretKey() { - Intent intent = new Intent(this, SelectSecretKeyActivity.class); - startActivityForResult(intent, Id.request.secret_keys); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - - case Id.request.secret_keys: { - if (resultCode == RESULT_OK) { - Bundle bundle = data.getExtras(); - mSecretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID); - } else { - mSecretKeyId = Id.key.none; - } - updateSelectedKeyView(mSecretKeyId); - break; - } - - default: { - break; - } - } - - super.onActivityResult(requestCode, resultCode, data); - } - - private void updateSelectedKeyView(long secretKeyId) { - if (secretKeyId == Id.key.none) { - keyUserId.setText(R.string.api_settings_no_key); - keyUserIdRest.setText(""); - } else { - String uid = getResources().getString(R.string.unknownUserId); - String uidExtra = ""; - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, - secretKeyId); - if (keyRing != null) { - PGPSecretKey key = PgpHelper.getMasterKey(keyRing); - if (key != null) { - String userId = PgpHelper.getMainUserIdSafe(this, key); - String chunks[] = userId.split(" <", 2); - uid = chunks[0]; - if (chunks.length > 1) { - uidExtra = "<" + chunks[1]; - } - } - } - keyUserId.setText(uid); - keyUserIdRest.setText(uidExtra); - } - } - } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java index 46cea389a..69d4e68ea 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -1,10 +1,21 @@ package org.sufficientlysecure.keychain.remote_api; +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.PgpHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity; +import org.sufficientlysecure.keychain.util.Log; +import android.app.Activity; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -14,29 +25,72 @@ import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TextView; public class AppSettingsFragment extends Fragment { - private LinearLayout advancedSettingsContainer; - private Button advancedSettingsButton; + // model + private long mSecretKeyId = Id.key.none; + + // view + private LinearLayout mAdvancedSettingsContainer; + private Button mAdvancedSettingsButton; + private TextView mAppNameView; + private ImageView mAppIconView; + private TextView mKeyUserId; + private TextView mKeyUserIdRest; + private Button mSelectKeyButton; + private CheckBox mAsciiArmorCheckBox; + + public void setSecretKey(long keyId) { + mSecretKeyId = keyId; + updateSelectedKeyView(keyId); + } + + public long getSecretKeyId() { + return mSecretKeyId; + } + + public void setAsciiArmor(boolean value) { + mAsciiArmorCheckBox.setChecked(value); + } + + public boolean isAsciiArmor() { + return mAsciiArmorCheckBox.isChecked(); + } /** * Inflate the layout for this fragment */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.api_app_settings_fragment, container, false); + View view = inflater.inflate(R.layout.api_app_settings_fragment, container, false); + initView(view); + return view; } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + private void initView(View view) { + mAdvancedSettingsButton = (Button) view.findViewById(R.id.api_app_settings_advanced_button); + mAdvancedSettingsContainer = (LinearLayout) view + .findViewById(R.id.api_app_settings_advanced); + + mAppNameView = (TextView) view.findViewById(R.id.api_app_settings_app_name); + mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon); + mKeyUserId = (TextView) view.findViewById(R.id.api_app_settings_user_id); + mKeyUserIdRest = (TextView) view.findViewById(R.id.api_app_settings_user_id_rest); + mSelectKeyButton = (Button) view.findViewById(R.id.api_app_settings_select_key_button); + mAsciiArmorCheckBox = (CheckBox) view.findViewById(R.id.api_app_ascii_armor); + + mSelectKeyButton.setOnClickListener(new OnClickListener() { - advancedSettingsButton = (Button) getActivity().findViewById( - R.id.api_app_settings_advanced_button); - advancedSettingsContainer = (LinearLayout) getActivity().findViewById( - R.id.api_app_settings_advanced); + @Override + public void onClick(View v) { + selectSecretKey(); + } + }); final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f); visibleAnimation.setDuration(250); @@ -49,21 +103,102 @@ public class AppSettingsFragment extends Fragment { // Animation.RELATIVE_TO_SELF, 0.0f); // animation2.setDuration(150); - advancedSettingsButton.setOnClickListener(new OnClickListener() { + mAdvancedSettingsButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - if (advancedSettingsContainer.getVisibility() == View.VISIBLE) { - advancedSettingsContainer.startAnimation(invisibleAnimation); - advancedSettingsContainer.setVisibility(View.INVISIBLE); - advancedSettingsButton.setText(R.string.api_settings_show_advanced); + if (mAdvancedSettingsContainer.getVisibility() == View.VISIBLE) { + mAdvancedSettingsContainer.startAnimation(invisibleAnimation); + mAdvancedSettingsContainer.setVisibility(View.INVISIBLE); + mAdvancedSettingsButton.setText(R.string.api_settings_show_advanced); } else { - advancedSettingsContainer.startAnimation(visibleAnimation); - advancedSettingsContainer.setVisibility(View.VISIBLE); - advancedSettingsButton.setText(R.string.api_settings_hide_advanced); + mAdvancedSettingsContainer.startAnimation(visibleAnimation); + mAdvancedSettingsContainer.setVisibility(View.VISIBLE); + mAdvancedSettingsButton.setText(R.string.api_settings_hide_advanced); } } }); } + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + } + + private void selectSecretKey() { + Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class); + startActivityForResult(intent, Id.request.secret_keys); + } + + public void setPackage(String packageName) { + PackageManager pm = getActivity().getApplicationContext().getPackageManager(); + + // get application name and icon from package manager + String appName = null; + Drawable appIcon = null; + try { + ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); + + appName = (String) pm.getApplicationLabel(ai); + appIcon = pm.getApplicationIcon(ai); + } catch (final NameNotFoundException e) { + // fallback + appName = packageName; + } + mAppNameView.setText(appName); + mAppIconView.setImageDrawable(appIcon); + } + + private void updateSelectedKeyView(long secretKeyId) { + if (secretKeyId == Id.key.none) { + mKeyUserId.setText(R.string.api_settings_no_key); + mKeyUserIdRest.setText(""); + } else { + String uid = getResources().getString(R.string.unknownUserId); + String uidExtra = ""; + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId( + getActivity(), secretKeyId); + if (keyRing != null) { + PGPSecretKey key = PgpHelper.getMasterKey(keyRing); + if (key != null) { + String userId = PgpHelper.getMainUserIdSafe(getActivity(), key); + String chunks[] = userId.split(" <", 2); + uid = chunks[0]; + if (chunks.length > 1) { + uidExtra = "<" + chunks[1]; + } + } + } + mKeyUserId.setText(uid); + mKeyUserIdRest.setText(uidExtra); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d(Constants.TAG, "onactivityresult " + requestCode + " " + resultCode); + switch (requestCode) { + + case Id.request.secret_keys: { + if (resultCode == Activity.RESULT_OK) { + Bundle bundle = data.getExtras(); + mSecretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID); + Log.d(Constants.TAG, "jo " + mSecretKeyId); + + } else { + mSecretKeyId = Id.key.none; + } + updateSelectedKeyView(mSecretKeyId); + break; + } + + default: { + break; + } + } + + super.onActivityResult(requestCode, resultCode, data); + } + } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 00bba7757..5f36075f5 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -16,8 +16,6 @@ package org.sufficientlysecure.keychain.remote_api; -import java.util.ArrayList; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; @@ -26,6 +24,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockFragmentActivity; import android.content.ComponentName; @@ -38,10 +37,10 @@ import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.LinearLayout; +import android.view.ViewGroup; +import android.widget.TextView; public class ServiceActivity extends SherlockFragmentActivity { @@ -133,8 +132,63 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + // BEGIN_INCLUDE (inflate_set_custom_view) + // Inflate a "Done"/"Cancel" custom action bar view + final LayoutInflater inflater = (LayoutInflater) getSupportActionBar() + .getThemedContext().getSystemService(LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater.inflate( + R.layout.actionbar_custom_view_done_cancel, null); + + ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)) + .setText(R.string.api_register_allow); + customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Allow + ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); + // Intent data = new Intent(); + + try { + mServiceCallback.onRegistered(true, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); + } + }); + ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)) + .setText(R.string.api_register_disallow); + customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Disallow + try { + mServiceCallback.onRegistered(false, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); + } + }); + + // Show the custom action bar view and hide the normal Home icon and title. + final ActionBar actionBar = getSupportActionBar(); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, + ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME + | ActionBar.DISPLAY_SHOW_TITLE); + actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + // END_INCLUDE (inflate_set_custom_view) + setContentView(R.layout.api_app_register_activity); + AppSettingsFragment settingsFragment = (AppSettingsFragment) getSupportFragmentManager() + .findFragmentById(R.id.api_app_settings_fragment); + + settingsFragment.setPackage(packageName); + // TODO: handle if app is already registered // LinearLayout layoutRegister = (LinearLayout) // findViewById(R.id.register_crypto_consumer_register_layout); @@ -152,37 +206,6 @@ public class ServiceActivity extends SherlockFragmentActivity { // layoutEdit.setVisibility(View.GONE); // } - Button allowButton = (Button) findViewById(R.id.api_register_allow); - Button disallowButton = (Button) findViewById(R.id.api_register_disallow); - - allowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); - // Intent data = new Intent(); - - try { - mServiceCallback.onRegistered(true, packageName); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); - } - finish(); - } - }); - - disallowButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - try { - mServiceCallback.onRegistered(false, packageName); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); - } - finish(); - } - }); } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); -- cgit v1.2.3 From c97c57d34ea1994312ad7e409042ec55cf27c1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 10:03:25 +0200 Subject: remove dead code --- .../keychain/remote_api/AppSettingsActivity.java | 15 ++------ .../keychain/remote_api/ServiceActivity.java | 41 +++++++++++++--------- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 4e069f3b0..55fa72b0e 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -12,7 +12,6 @@ import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; import android.widget.TextView; import com.actionbarsherlock.app.ActionBar; @@ -22,22 +21,15 @@ import com.actionbarsherlock.view.MenuItem; public class AppSettingsActivity extends SherlockFragmentActivity { // model - Uri mAppUri; - String mPackageName; + private Uri mAppUri; + private String mPackageName; - // view - Button saveButton; - Button revokeButton; - - AppSettingsFragment settingsFragment; + private AppSettingsFragment settingsFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // pm = getApplicationContext().getPackageManager(); - - // BEGIN_INCLUDE (inflate_set_custom_view) // Inflate a "Done" custom action bar view to serve as the "Up" affordance. final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext() .getSystemService(LAYOUT_INFLATER_SERVICE); @@ -60,7 +52,6 @@ public class AppSettingsActivity extends SherlockFragmentActivity { actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE); actionBar.setCustomView(customActionBarView); - // END_INCLUDE (inflate_set_custom_view) setContentView(R.layout.api_app_settings_activity); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java index 5f36075f5..422026a19 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java @@ -17,16 +17,13 @@ package org.sufficientlysecure.keychain.remote_api; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; import org.sufficientlysecure.keychain.helper.PgpMain; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; - import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -41,6 +38,10 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.Toast; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; public class ServiceActivity extends SherlockFragmentActivity { @@ -53,6 +54,9 @@ public class ServiceActivity extends SherlockFragmentActivity { private IServiceActivityCallback mServiceCallback; private boolean mServiceBound; + // view + AppSettingsFragment settingsFragment; + private ServiceConnection mServiceActivityConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { mServiceCallback = IServiceActivityCallback.Stub.asInterface(service); @@ -132,7 +136,6 @@ public class ServiceActivity extends SherlockFragmentActivity { if (ACTION_REGISTER.equals(action)) { final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - // BEGIN_INCLUDE (inflate_set_custom_view) // Inflate a "Done"/"Cancel" custom action bar view final LayoutInflater inflater = (LayoutInflater) getSupportActionBar() .getThemedContext().getSystemService(LAYOUT_INFLATER_SERVICE); @@ -146,15 +149,22 @@ public class ServiceActivity extends SherlockFragmentActivity { @Override public void onClick(View v) { // Allow - ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); - // Intent data = new Intent(); - try { - mServiceCallback.onRegistered(true, packageName); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); + if (settingsFragment.getSecretKeyId() == Id.key.none) { + Toast.makeText(ServiceActivity.this, + R.string.api_register_error_select_key, Toast.LENGTH_LONG) + .show(); + } else { + ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); + // Intent data = new Intent(); + + try { + mServiceCallback.onRegistered(true, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); } - finish(); } }); ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)) @@ -180,13 +190,12 @@ public class ServiceActivity extends SherlockFragmentActivity { | ActionBar.DISPLAY_SHOW_TITLE); actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - // END_INCLUDE (inflate_set_custom_view) setContentView(R.layout.api_app_register_activity); - AppSettingsFragment settingsFragment = (AppSettingsFragment) getSupportFragmentManager() - .findFragmentById(R.id.api_app_settings_fragment); - + settingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( + R.id.api_app_settings_fragment); + settingsFragment.setPackage(packageName); // TODO: handle if app is already registered -- cgit v1.2.3 From dc6a709b7a8f3b80039c7de40050b9f2f3f42dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 11:24:28 +0200 Subject: Disable parts of the old API --- .../keychain/helper/OtherHelper.java | 45 ++++++++++++---------- .../keychain/provider/KeychainProvider.java | 12 +++--- .../remote_api/RegisteredAppsListFragment.java | 8 ++-- 3 files changed, 35 insertions(+), 30 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java index 6a71ca0ba..e38b1b726 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java @@ -122,26 +122,31 @@ public class OtherHelper { if (action != null) { PackageManager pkgManager = activity.getPackageManager(); - for (int i = 0; i < restrictedActions.length; i++) { - if (restrictedActions[i].equals(action)) { - if (pkgName != null - && (pkgManager.checkPermission(permName, pkgName) == PackageManager.PERMISSION_GRANTED || pkgName - .equals(Constants.PACKAGE_NAME))) { - Log.d(Constants.TAG, pkgName + " has permission " + permName + ". Action " - + action + " was granted!"); - } else { - String error = pkgName + " does NOT have permission " + permName - + ". Action " + action + " was NOT granted!"; - Log.e(Constants.TAG, error); - Toast.makeText(activity, activity.getString(R.string.errorMessage, error), - Toast.LENGTH_LONG).show(); - - // end activity - activity.setResult(Activity.RESULT_CANCELED, null); - activity.finish(); - } - } - } +// for (int i = 0; i < restrictedActions.length; i++) { +// if (restrictedActions[i].equals(action)) { +// if (pkgName != null +// && (pkgManager.checkPermission(permName, pkgName) == PackageManager.PERMISSION_GRANTED || pkgName +// .equals(Constants.PACKAGE_NAME))) { +// Log.d(Constants.TAG, pkgName + " has permission " + permName + ". Action " +// + action + " was granted!"); +// } else { +// String error = pkgName + " does NOT have permission " + permName +// + ". Action " + action + " was NOT granted!"; +// Log.e(Constants.TAG, error); +// Toast.makeText(activity, activity.getString(R.string.errorMessage, error), +// Toast.LENGTH_LONG).show(); +// +// // end activity +// activity.setResult(Activity.RESULT_CANCELED, null); +// activity.finish(); +// } +// } +// } + + // TODO: currently always cancels! THis is the old API + // end activity + activity.setResult(Activity.RESULT_CANCELED, null); + activity.finish(); } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 98a45d69f..edb82e632 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -973,10 +973,12 @@ public class KeychainProvider extends ContentProvider { * updated, or deleted */ private void sendBroadcastDatabaseChange(int keyType, String contentItemType) { - Intent intent = new Intent(); - intent.setAction(ACTION_BROADCAST_DATABASE_CHANGE); - intent.putExtra(EXTRA_BROADCAST_KEY_TYPE, keyType); - intent.putExtra(EXTRA_BROADCAST_CONTENT_ITEM_TYPE, contentItemType); - getContext().sendBroadcast(intent, Constants.PERMISSION_ACCESS_API); + // TODO: Disabled, old API + // Intent intent = new Intent(); + // intent.setAction(ACTION_BROADCAST_DATABASE_CHANGE); + // intent.putExtra(EXTRA_BROADCAST_KEY_TYPE, keyType); + // intent.putExtra(EXTRA_BROADCAST_CONTENT_ITEM_TYPE, contentItemType); + // + // getContext().sendBroadcast(intent, Constants.PERMISSION_ACCESS_API); } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java index 5ab210d5f..d1e52a2d6 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/RegisteredAppsListFragment.java @@ -4,8 +4,6 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; -import com.actionbarsherlock.app.SherlockListFragment; - import android.content.ContentUris; import android.content.Intent; import android.database.Cursor; @@ -17,7 +15,8 @@ import android.support.v4.content.Loader; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; + +import com.actionbarsherlock.app.SherlockListFragment; public class RegisteredAppsListFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks { @@ -37,8 +36,7 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements public void onItemClick(AdapterView adapterView, View view, int position, long id) { // edit app settings Intent intent = new Intent(getActivity(), AppSettingsActivity.class); - intent.setData(ContentUris.withAppendedId( - KeychainContract.ApiApps.CONTENT_URI, id)); + intent.setData(ContentUris.withAppendedId(KeychainContract.ApiApps.CONTENT_URI, id)); startActivity(intent); } }); -- cgit v1.2.3 From 1beb85acf5d4900a9cc558d077b0df4ed6c683c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 11:55:08 +0200 Subject: Register works basically --- .../keychain/helper/OtherHelper.java | 2 +- .../keychain/provider/ProviderHelper.java | 11 +- .../keychain/remote_api/CryptoService.java | 39 +-- .../keychain/remote_api/CryptoServiceActivity.java | 266 +++++++++++++++++++++ .../keychain/remote_api/ServiceActivity.java | 263 -------------------- 5 files changed, 298 insertions(+), 283 deletions(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java delete mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java index e38b1b726..5dc561923 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java @@ -120,7 +120,7 @@ public class OtherHelper { public static void checkPackagePermissionForActions(Activity activity, String pkgName, String permName, String action, String[] restrictedActions) { if (action != null) { - PackageManager pkgManager = activity.getPackageManager(); +// PackageManager pkgManager = activity.getPackageManager(); // for (int i = 0; i < restrictedActions.length; i++) { // if (restrictedActions[i].equals(action)) { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java index c8f9baeff..60aa0542e 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -718,9 +718,9 @@ public class ProviderHelper { return cursor; } - public static ArrayList getCryptoConsumers(Context context) { - Cursor cursor = context.getContentResolver().query(ApiApps.CONTENT_URI, null, null, - null, null); + public static ArrayList getRegisteredApiApps(Context context) { + Cursor cursor = context.getContentResolver().query(ApiApps.CONTENT_URI, null, null, null, + null); ArrayList packageNames = new ArrayList(); if (cursor != null) { @@ -739,9 +739,12 @@ public class ProviderHelper { return packageNames; } - public static void addCryptoConsumer(Context context, String packageName) { + public static void addCryptoConsumer(Context context, String packageName, long keyId, + boolean asciiArmor) { ContentValues values = new ContentValues(); values.put(ApiApps.PACKAGE_NAME, packageName); + values.put(ApiApps.KEY_ID, keyId); + values.put(ApiApps.ASCII_ARMOR, asciiArmor); context.getContentResolver().insert(ApiApps.CONTENT_URI, values); } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java index 71b78ee01..2e6ab4263 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java @@ -76,10 +76,9 @@ public class CryptoService extends Service { public IBinder onBind(Intent intent) { // return different binder for connections from internal service activity if (ACTION_SERVICE_ACTIVITY.equals(intent.getAction())) { - String callingPackageName = intent.getPackage(); // this binder can only be used from OpenPGP Keychain - if (callingPackageName.equals(Constants.PACKAGE_NAME)) { + if (isCallerAllowed(true)) { return mBinderServiceActivity; } else { Log.e(Constants.TAG, "This binder can only be used from " + Constants.PACKAGE_NAME); @@ -150,8 +149,8 @@ public class CryptoService extends Service { // start passphrase dialog Bundle extras = new Bundle(); - extras.putLong(ServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_CACHE_PASSPHRASE, extras); + extras.putLong(CryptoServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); + pauseQueueAndStartServiceActivity(CryptoServiceActivity.ACTION_CACHE_PASSPHRASE, extras); } // if (signedOnly) { @@ -255,7 +254,7 @@ public class CryptoService extends Service { public void setup(boolean asciiArmor, boolean newKeyring, String newKeyringUserId) throws RemoteException { // TODO Auto-generated method stub - + } }; @@ -267,7 +266,7 @@ public class CryptoService extends Service { if (success) { // resume threads - if (isPackageAllowed(packageName)) { + if (isPackageAllowed(packageName, false)) { mThreadPool.resume(); } else { // TODO: should not happen? @@ -287,7 +286,7 @@ public class CryptoService extends Service { }; private void checkAndEnqueue(Runnable r) { - if (isCallerAllowed()) { + if (isCallerAllowed(false)) { mThreadPool.execute(r); Log.d(Constants.TAG, "Enqueued runnable…"); @@ -298,8 +297,8 @@ public class CryptoService extends Service { Log.e(Constants.TAG, "Not allowed to use service! Starting activity for registration!"); Bundle extras = new Bundle(); // TODO: currently simply uses first entry - extras.putString(ServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]); - pauseQueueAndStartServiceActivity(ServiceActivity.ACTION_REGISTER, extras); + extras.putString(CryptoServiceActivity.EXTRA_PACKAGE_NAME, callingPackages[0]); + pauseQueueAndStartServiceActivity(CryptoServiceActivity.ACTION_REGISTER, extras); mThreadPool.execute(r); @@ -311,16 +310,18 @@ public class CryptoService extends Service { * Checks if process that binds to this service (i.e. the package name corresponding to the * process) is in the list of allowed package names. * + * @param allowOnlySelf + * allow only Keychain app itself * @return true if process is allowed to use this service */ - private boolean isCallerAllowed() { + private boolean isCallerAllowed(boolean allowOnlySelf) { String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); // is calling package allowed to use this service? for (int i = 0; i < callingPackages.length; i++) { String currentPkg = callingPackages[i]; - if (isPackageAllowed(currentPkg)) { + if (isPackageAllowed(currentPkg, allowOnlySelf)) { return true; } } @@ -329,14 +330,22 @@ public class CryptoService extends Service { return false; } - private boolean isPackageAllowed(String packageName) { + /** + * Checks if packageName is a registered app for the API. + * + * @param packageName + * @param allowOnlySelf + * allow only Keychain app itself + * @return + */ + private boolean isPackageAllowed(String packageName, boolean allowOnlySelf) { Log.d(Constants.TAG, "packageName: " + packageName); - ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(mContext); + ArrayList allowedPkgs = ProviderHelper.getRegisteredApiApps(mContext); Log.d(Constants.TAG, "allowed: " + allowedPkgs); // check if package is allowed to use our service - if (allowedPkgs.contains(packageName)) { + if (allowedPkgs.contains(packageName) && (!allowOnlySelf)) { Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); return true; @@ -353,7 +362,7 @@ public class CryptoService extends Service { mThreadPool.pause(); Log.d(Constants.TAG, "starting activity..."); - Intent intent = new Intent(getBaseContext(), ServiceActivity.class); + Intent intent = new Intent(getBaseContext(), CryptoServiceActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(action); if (extras != null) { diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java new file mode 100644 index 000000000..39ff79f16 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2013 Dominik Schürmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.PgpMain; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Log; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class CryptoServiceActivity extends SherlockFragmentActivity { + + public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.remote_api.REGISTER"; + public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.remote_api.CRYPTO_CACHE_PASSPHRASE"; + + public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; + public static final String EXTRA_PACKAGE_NAME = "packageName"; + + private IServiceActivityCallback mServiceCallback; + private boolean mServiceBound; + + // view + AppSettingsFragment settingsFragment; + + private ServiceConnection mServiceActivityConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mServiceCallback = IServiceActivityCallback.Stub.asInterface(service); + Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); + mServiceBound = true; + } + + public void onServiceDisconnected(ComponentName name) { + mServiceCallback = null; + Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); + mServiceBound = false; + } + }; + + /** + * If not already bound, bind! + * + * @return + */ + public boolean bindToService() { + if (mServiceCallback == null && !mServiceBound) { // if not already connected + try { + Log.d(Constants.TAG, "not bound yet"); + + Intent serviceIntent = new Intent(); + serviceIntent + .setAction("org.sufficientlysecure.keychain.crypto_provider.IServiceActivityCallback"); + bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); + + return true; + } catch (Exception e) { + Log.d(Constants.TAG, "Exception", e); + return false; + } + } else { // already connected + Log.d(Constants.TAG, "already bound... "); + return true; + } + } + + public void unbindFromService() { + unbindService(mServiceActivityConnection); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.d(Constants.TAG, "onCreate…"); + + // bind to our own crypto service + bindToService(); + + handleActions(getIntent()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // unbind from our crypto service + if (mServiceActivityConnection != null) { + unbindFromService(); + } + } + + protected void handleActions(Intent intent) { + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + /** + * com.android.crypto actions + */ + if (ACTION_REGISTER.equals(action)) { + final String packageName = extras.getString(EXTRA_PACKAGE_NAME); + + // Inflate a "Done"/"Cancel" custom action bar view + final LayoutInflater inflater = (LayoutInflater) getSupportActionBar() + .getThemedContext().getSystemService(LAYOUT_INFLATER_SERVICE); + final View customActionBarView = inflater.inflate( + R.layout.actionbar_custom_view_done_cancel, null); + + ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)) + .setText(R.string.api_register_allow); + customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Allow + + if (settingsFragment.getSecretKeyId() == Id.key.none) { + Toast.makeText(CryptoServiceActivity.this, + R.string.api_register_error_select_key, Toast.LENGTH_LONG) + .show(); + } else { + ProviderHelper.addCryptoConsumer(CryptoServiceActivity.this, + packageName, settingsFragment.getSecretKeyId(), + settingsFragment.isAsciiArmor()); + // Intent data = new Intent(); + + try { + mServiceCallback.onRegistered(true, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); + } + } + }); + ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)) + .setText(R.string.api_register_disallow); + customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Disallow + try { + mServiceCallback.onRegistered(false, packageName); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); + } + }); + + // Show the custom action bar view and hide the normal Home icon and title. + final ActionBar actionBar = getSupportActionBar(); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, + ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME + | ActionBar.DISPLAY_SHOW_TITLE); + actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + + setContentView(R.layout.api_app_register_activity); + + settingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( + R.id.api_app_settings_fragment); + + settingsFragment.setPackage(packageName); + + // TODO: handle if app is already registered + // LinearLayout layoutRegister = (LinearLayout) + // findViewById(R.id.register_crypto_consumer_register_layout); + // LinearLayout layoutEdit = (LinearLayout) + // findViewById(R.id.register_crypto_consumer_edit_layout); + // + // // if already registered show edit buttons + // ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(this); + // if (allowedPkgs.contains(packageName)) { + // Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + // layoutRegister.setVisibility(View.GONE); + // layoutEdit.setVisibility(View.VISIBLE); + // } else { + // layoutRegister.setVisibility(View.VISIBLE); + // layoutEdit.setVisibility(View.GONE); + // } + + } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { + long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); + + showPassphraseDialog(secretKeyId); + } else { + Log.e(Constants.TAG, "Wrong action!"); + finish(); + } + } + + /** + * Shows passphrase dialog to cache a new passphrase the user enters for using it later for + * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks + * for a symmetric passphrase + */ + private void showPassphraseDialog(long secretKeyId) { + // Message is received after passphrase is cached + Handler returnHandler = new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + try { + mServiceCallback.onCachedPassphrase(true); + } catch (RemoteException e) { + Log.e(Constants.TAG, "ServiceActivity"); + } + finish(); + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(returnHandler); + + try { + PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, + messenger, secretKeyId); + + passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); + } catch (PgpMain.PgpGeneralException e) { + Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); + // send message to handler to start encryption directly + returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); + } + } +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java deleted file mode 100644 index 422026a19..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/ServiceActivity.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.remote_api; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.PgpMain; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import android.widget.Toast; - -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; - -public class ServiceActivity extends SherlockFragmentActivity { - - public static final String ACTION_REGISTER = "org.sufficientlysecure.keychain.remote_api.REGISTER"; - public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.remote_api.CRYPTO_CACHE_PASSPHRASE"; - - public static final String EXTRA_SECRET_KEY_ID = "secretKeyId"; - public static final String EXTRA_PACKAGE_NAME = "packageName"; - - private IServiceActivityCallback mServiceCallback; - private boolean mServiceBound; - - // view - AppSettingsFragment settingsFragment; - - private ServiceConnection mServiceActivityConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - mServiceCallback = IServiceActivityCallback.Stub.asInterface(service); - Log.d(Constants.TAG, "connected to ICryptoServiceActivity"); - mServiceBound = true; - } - - public void onServiceDisconnected(ComponentName name) { - mServiceCallback = null; - Log.d(Constants.TAG, "disconnected from ICryptoServiceActivity"); - mServiceBound = false; - } - }; - - /** - * If not already bound, bind! - * - * @return - */ - public boolean bindToService() { - if (mServiceCallback == null && !mServiceBound) { // if not already connected - try { - Log.d(Constants.TAG, "not bound yet"); - - Intent serviceIntent = new Intent(); - serviceIntent.setAction("org.openintents.crypto.ICryptoService"); - bindService(serviceIntent, mServiceActivityConnection, Context.BIND_AUTO_CREATE); - - return true; - } catch (Exception e) { - Log.d(Constants.TAG, "Exception", e); - return false; - } - } else { // already connected - Log.d(Constants.TAG, "already bound... "); - return true; - } - } - - public void unbindFromService() { - unbindService(mServiceActivityConnection); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d(Constants.TAG, "onCreate…"); - - // bind to our own crypto service - bindToService(); - - handleActions(getIntent()); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - // unbind from our crypto service - if (mServiceActivityConnection != null) { - unbindFromService(); - } - } - - protected void handleActions(Intent intent) { - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - /** - * com.android.crypto actions - */ - if (ACTION_REGISTER.equals(action)) { - final String packageName = extras.getString(EXTRA_PACKAGE_NAME); - - // Inflate a "Done"/"Cancel" custom action bar view - final LayoutInflater inflater = (LayoutInflater) getSupportActionBar() - .getThemedContext().getSystemService(LAYOUT_INFLATER_SERVICE); - final View customActionBarView = inflater.inflate( - R.layout.actionbar_custom_view_done_cancel, null); - - ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text)) - .setText(R.string.api_register_allow); - customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Allow - - if (settingsFragment.getSecretKeyId() == Id.key.none) { - Toast.makeText(ServiceActivity.this, - R.string.api_register_error_select_key, Toast.LENGTH_LONG) - .show(); - } else { - ProviderHelper.addCryptoConsumer(ServiceActivity.this, packageName); - // Intent data = new Intent(); - - try { - mServiceCallback.onRegistered(true, packageName); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); - } - finish(); - } - } - }); - ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text)) - .setText(R.string.api_register_disallow); - customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Disallow - try { - mServiceCallback.onRegistered(false, packageName); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); - } - finish(); - } - }); - - // Show the custom action bar view and hide the normal Home icon and title. - final ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, - ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME - | ActionBar.DISPLAY_SHOW_TITLE); - actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - - setContentView(R.layout.api_app_register_activity); - - settingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( - R.id.api_app_settings_fragment); - - settingsFragment.setPackage(packageName); - - // TODO: handle if app is already registered - // LinearLayout layoutRegister = (LinearLayout) - // findViewById(R.id.register_crypto_consumer_register_layout); - // LinearLayout layoutEdit = (LinearLayout) - // findViewById(R.id.register_crypto_consumer_edit_layout); - // - // // if already registered show edit buttons - // ArrayList allowedPkgs = ProviderHelper.getCryptoConsumers(this); - // if (allowedPkgs.contains(packageName)) { - // Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); - // layoutRegister.setVisibility(View.GONE); - // layoutEdit.setVisibility(View.VISIBLE); - // } else { - // layoutRegister.setVisibility(View.VISIBLE); - // layoutEdit.setVisibility(View.GONE); - // } - - } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { - long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); - - showPassphraseDialog(secretKeyId); - } else { - Log.e(Constants.TAG, "Wrong action!"); - finish(); - } - } - - /** - * Shows passphrase dialog to cache a new passphrase the user enters for using it later for - * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks - * for a symmetric passphrase - */ - private void showPassphraseDialog(long secretKeyId) { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - try { - mServiceCallback.onCachedPassphrase(true); - } catch (RemoteException e) { - Log.e(Constants.TAG, "ServiceActivity"); - } - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - try { - PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this, - messenger, secretKeyId); - - passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PgpMain.PgpGeneralException e) { - Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); - // send message to handler to start encryption directly - returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); - } - } -} -- cgit v1.2.3 From fabb0389fc6c4b8a92d2681c8dc647b66e687b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 12:34:06 +0200 Subject: Put model into own class for easier use in service --- .../keychain/provider/ProviderHelper.java | 49 +++++++++++++-- .../keychain/remote_api/AppSettings.java | 70 ++++++++++++++++++++++ .../keychain/remote_api/AppSettingsActivity.java | 38 ++---------- .../keychain/remote_api/AppSettingsFragment.java | 44 +++++++------- .../keychain/remote_api/CryptoServiceActivity.java | 13 ++-- 5 files changed, 149 insertions(+), 65 deletions(-) create mode 100644 OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettings.java (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 60aa0542e..42210db6a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -36,6 +36,7 @@ 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.provider.KeychainDatabase.Tables; +import org.sufficientlysecure.keychain.remote_api.AppSettings; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -739,12 +740,50 @@ public class ProviderHelper { return packageNames; } - public static void addCryptoConsumer(Context context, String packageName, long keyId, - boolean asciiArmor) { + private static void contentValueForApiApps() { + + } + + public static void insertApiApp(Context context, AppSettings appSettings) { ContentValues values = new ContentValues(); - values.put(ApiApps.PACKAGE_NAME, packageName); - values.put(ApiApps.KEY_ID, keyId); - values.put(ApiApps.ASCII_ARMOR, asciiArmor); + values.put(ApiApps.PACKAGE_NAME, appSettings.getPackageName()); + values.put(ApiApps.KEY_ID, appSettings.getKeyId()); + values.put(ApiApps.ASCII_ARMOR, appSettings.isAsciiArmor()); + // TODO: other parameters context.getContentResolver().insert(ApiApps.CONTENT_URI, values); } + + public static void updateApiApp(Context context, AppSettings appSettings, Uri uri) { + final ContentValues cv = new ContentValues(); + cv.put(KeychainContract.ApiApps.KEY_ID, appSettings.getKeyId()); + + cv.put(KeychainContract.ApiApps.ASCII_ARMOR, appSettings.isAsciiArmor()); + // TODO: other parameters + + if (context.getContentResolver().update(uri, cv, null, null) <= 0) { + throw new RuntimeException(); + } + } + + public static AppSettings getApiAppSettings(Context context, Uri uri) { + AppSettings settings = new AppSettings(); + Cursor cur = context.getContentResolver().query(uri, null, null, null, null); + if (cur.moveToFirst()) { + settings.setPackageName(cur.getString(cur + .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); + + settings.setKeyId(cur.getLong(cur.getColumnIndex(KeychainContract.ApiApps.KEY_ID))); + + settings.setAsciiArmor(cur.getInt(cur + .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); + + settings.setPackageName(cur.getString(cur + .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); + + settings.setPackageName(cur.getString(cur + .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); + } + + return settings; + } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettings.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettings.java new file mode 100644 index 000000000..fe251a5e7 --- /dev/null +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettings.java @@ -0,0 +1,70 @@ +package org.sufficientlysecure.keychain.remote_api; + +import org.sufficientlysecure.keychain.Id; + +public class AppSettings { + private String packageName; + private long keyId = Id.key.none; + private boolean asciiArmor; + private int encryptionAlgorithm = 7; // AES-128 + private int hashAlgorithm = 10; // SHA-512 + private int compression = 2; // zlib + + public AppSettings() { + + } + + public AppSettings(String packageName) { + super(); + this.packageName = packageName; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public long getKeyId() { + return keyId; + } + + public void setKeyId(long scretKeyId) { + this.keyId = scretKeyId; + } + + public boolean isAsciiArmor() { + return asciiArmor; + } + + public void setAsciiArmor(boolean asciiArmor) { + this.asciiArmor = asciiArmor; + } + + public int getEncryptionAlgorithm() { + return encryptionAlgorithm; + } + + public void setEncryptionAlgorithm(int encryptionAlgorithm) { + this.encryptionAlgorithm = encryptionAlgorithm; + } + + public int getHashAlgorithm() { + return hashAlgorithm; + } + + public void setHashAlgorithm(int hashAlgorithm) { + this.hashAlgorithm = hashAlgorithm; + } + + public int getCompression() { + return compression; + } + + public void setCompression(int compression) { + this.compression = compression; + } + +} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java index 55fa72b0e..155369601 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsActivity.java @@ -2,12 +2,10 @@ package org.sufficientlysecure.keychain.remote_api; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; -import android.content.ContentValues; import android.content.Intent; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; @@ -20,9 +18,7 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; public class AppSettingsActivity extends SherlockFragmentActivity { - // model private Uri mAppUri; - private String mPackageName; private AppSettingsFragment settingsFragment; @@ -91,26 +87,8 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } private void loadData(Uri appUri) { - Cursor cur = getContentResolver().query(appUri, null, null, null, null); - if (cur.moveToFirst()) { - mPackageName = cur.getString(cur.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)); - - settingsFragment.setPackage(mPackageName); - - try { - long secretKeyId = (cur.getLong(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.KEY_ID))); - Log.d(Constants.TAG, "mSecretKeyId: " + secretKeyId); - settingsFragment.setSecretKey(secretKeyId); - - boolean asciiArmor = (cur.getInt(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.ASCII_ARMOR)) == 1); - settingsFragment.setAsciiArmor(asciiArmor); - - } catch (IllegalArgumentException e) { - Log.e(Constants.TAG, "AppSettingsActivity", e); - } - } + AppSettings settings = ProviderHelper.getApiAppSettings(this, appUri); + settingsFragment.setAppSettings(settings); } private void revokeAccess() { @@ -121,15 +99,7 @@ public class AppSettingsActivity extends SherlockFragmentActivity { } private void save() { - final ContentValues cv = new ContentValues(); - cv.put(KeychainContract.ApiApps.KEY_ID, settingsFragment.getSecretKeyId()); - - cv.put(KeychainContract.ApiApps.ASCII_ARMOR, settingsFragment.isAsciiArmor()); - // TODO: other parameters - - if (getContentResolver().update(mAppUri, cv, null, null) <= 0) { - throw new RuntimeException(); - } + ProviderHelper.updateApiApp(this, settingsFragment.getAppSettings(), mAppUri); finish(); } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java index 69d4e68ea..1bb447a7d 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/AppSettingsFragment.java @@ -26,6 +26,8 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.Button; import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -33,7 +35,7 @@ import android.widget.TextView; public class AppSettingsFragment extends Fragment { // model - private long mSecretKeyId = Id.key.none; + private AppSettings appSettings; // view private LinearLayout mAdvancedSettingsContainer; @@ -45,21 +47,15 @@ public class AppSettingsFragment extends Fragment { private Button mSelectKeyButton; private CheckBox mAsciiArmorCheckBox; - public void setSecretKey(long keyId) { - mSecretKeyId = keyId; - updateSelectedKeyView(keyId); + public AppSettings getAppSettings() { + return appSettings; } - public long getSecretKeyId() { - return mSecretKeyId; - } - - public void setAsciiArmor(boolean value) { - mAsciiArmorCheckBox.setChecked(value); - } - - public boolean isAsciiArmor() { - return mAsciiArmorCheckBox.isChecked(); + public void setAppSettings(AppSettings appSettings) { + this.appSettings = appSettings; + setPackage(appSettings.getPackageName()); + updateSelectedKeyView(appSettings.getKeyId()); + mAsciiArmorCheckBox.setChecked(appSettings.isAsciiArmor()); } /** @@ -92,6 +88,14 @@ public class AppSettingsFragment extends Fragment { } }); + mAsciiArmorCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + appSettings.setAsciiArmor(isChecked); + } + }); + final Animation visibleAnimation = new AlphaAnimation(0.0f, 1.0f); visibleAnimation.setDuration(250); final Animation invisibleAnimation = new AlphaAnimation(1.0f, 0.0f); @@ -123,7 +127,6 @@ public class AppSettingsFragment extends Fragment { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - } private void selectSecretKey() { @@ -131,7 +134,7 @@ public class AppSettingsFragment extends Fragment { startActivityForResult(intent, Id.request.secret_keys); } - public void setPackage(String packageName) { + private void setPackage(String packageName) { PackageManager pm = getActivity().getApplicationContext().getPackageManager(); // get application name and icon from package manager @@ -181,15 +184,16 @@ public class AppSettingsFragment extends Fragment { switch (requestCode) { case Id.request.secret_keys: { + long secretKeyId; if (resultCode == Activity.RESULT_OK) { Bundle bundle = data.getExtras(); - mSecretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID); - Log.d(Constants.TAG, "jo " + mSecretKeyId); + secretKeyId = bundle.getLong(SelectSecretKeyActivity.RESULT_EXTRA_MASTER_KEY_ID); } else { - mSecretKeyId = Id.key.none; + secretKeyId = Id.key.none; } - updateSelectedKeyView(mSecretKeyId); + appSettings.setKeyId(secretKeyId); + updateSelectedKeyView(secretKeyId); break; } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java index 39ff79f16..06c64559a 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoServiceActivity.java @@ -151,15 +151,14 @@ public class CryptoServiceActivity extends SherlockFragmentActivity { public void onClick(View v) { // Allow - if (settingsFragment.getSecretKeyId() == Id.key.none) { + // user needs to select a key! + if (settingsFragment.getAppSettings().getKeyId() == Id.key.none) { Toast.makeText(CryptoServiceActivity.this, R.string.api_register_error_select_key, Toast.LENGTH_LONG) .show(); } else { - ProviderHelper.addCryptoConsumer(CryptoServiceActivity.this, - packageName, settingsFragment.getSecretKeyId(), - settingsFragment.isAsciiArmor()); - // Intent data = new Intent(); + ProviderHelper.insertApiApp(CryptoServiceActivity.this, + settingsFragment.getAppSettings()); try { mServiceCallback.onRegistered(true, packageName); @@ -199,7 +198,9 @@ public class CryptoServiceActivity extends SherlockFragmentActivity { settingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById( R.id.api_app_settings_fragment); - settingsFragment.setPackage(packageName); + AppSettings settings = new AppSettings(packageName); + settingsFragment.setAppSettings(settings); + // TODO: handle if app is already registered // LinearLayout layoutRegister = (LinearLayout) -- cgit v1.2.3 From 3a66c1c25aff1dadf4779c2df0fac04f3a9f3c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 6 Sep 2013 13:48:27 +0200 Subject: Testing encrypt by service --- .../keychain/provider/ProviderHelper.java | 3 + .../keychain/remote_api/CryptoService.java | 85 +++++++++++++++------- .../keychain/service/PassphraseCacheService.java | 2 +- 3 files changed, 64 insertions(+), 26 deletions(-) (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain') diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 42210db6a..d0fcfe999 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -768,6 +768,9 @@ public class ProviderHelper { public static AppSettings getApiAppSettings(Context context, Uri uri) { AppSettings settings = new AppSettings(); Cursor cur = context.getContentResolver().query(uri, null, null, null, null); + if (cur == null) { + return null; + } if (cur.moveToFirst()) { settings.setPackageName(cur.getString(cur .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java index 2e6ab4263..125967c66 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/remote_api/CryptoService.java @@ -23,6 +23,7 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.prefs.Preferences; import org.openintents.crypto.CryptoError; import org.openintents.crypto.CryptoSignatureResult; @@ -32,18 +33,19 @@ import org.sufficientlysecure.keychain.helper.PgpMain; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote_api.IServiceActivityCallback; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.util.PausableThreadPoolExecutor; - import org.openintents.crypto.ICryptoCallback; import org.openintents.crypto.ICryptoService; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -89,29 +91,50 @@ public class CryptoService extends Service { } } + private String getCachedPassphrase(long keyId) { + String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, keyId); + + if (passphrase == null) { + Log.d(Constants.TAG, "No passphrase! Activity required!"); + + // start passphrase dialog + Bundle extras = new Bundle(); + extras.putLong(CryptoServiceActivity.EXTRA_SECRET_KEY_ID, keyId); + pauseQueueAndStartServiceActivity(CryptoServiceActivity.ACTION_CACHE_PASSPHRASE, extras); + } + + return passphrase; + } + private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds, - ICryptoCallback callback) throws RemoteException { + AppSettings appSettings, ICryptoCallback callback) throws RemoteException { try { // build InputData and write into OutputStream InputStream inputStream = new ByteArrayInputStream(inputBytes); long inputLength = inputBytes.length; InputData inputData = new InputData(inputStream, inputLength); - OutputStream outStream = new ByteArrayOutputStream(); + OutputStream outputStream = new ByteArrayOutputStream(); + + String passphrase = getCachedPassphrase(appSettings.getKeyId()); + + PgpMain.encryptAndSign(mContext, null, inputData, outputStream, + appSettings.isAsciiArmor(), appSettings.getCompression(), new long[] {}, + "test", appSettings.getEncryptionAlgorithm(), Id.key.none, + appSettings.getHashAlgorithm(), true, passphrase); + + // PgpMain.encryptAndSign(this, this, inputData, outputStream, + // appSettings.isAsciiArmor(), + // appSettings.getCompression(), encryptionKeyIds, encryptionPassphrase, + // appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(), + // appSettings.getHashAlgorithm(), true, passphrase); - // TODO: hardcoded... - boolean useAsciiArmor = true; - int compressionId = 2; // zlib + outputStream.close(); - // PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor, - // compressionId, encryptionKeyIds, encryptionPassphrase, Preferences - // .getPreferences(this).getDefaultEncryptionAlgorithm(), - // secretKeyId, - // Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences - // .getPreferences(this).getForceV3Signatures(), - // PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); + byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - outStream.close(); + // return over handler on client side + callback.onSuccess(outputBytes, null); } catch (Exception e) { Log.e(Constants.TAG, "KeychainService, Exception!", e); @@ -133,6 +156,8 @@ public class CryptoService extends Service { OutputStream outputStream = new ByteArrayOutputStream(); + // TODO: This allows to decrypt messages with ALL secret keys, not only the one for the + // app, Fix this? long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream); if (secretKeyId == Id.key.none) { throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound)); @@ -142,16 +167,7 @@ public class CryptoService extends Service { Log.d(Constants.TAG, "secretKeyId " + secretKeyId); - String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, secretKeyId); - - if (passphrase == null) { - Log.d(Constants.TAG, "No passphrase! Activity required!"); - - // start passphrase dialog - Bundle extras = new Bundle(); - extras.putLong(CryptoServiceActivity.EXTRA_SECRET_KEY_ID, secretKeyId); - pauseQueueAndStartServiceActivity(CryptoServiceActivity.ACTION_CACHE_PASSPHRASE, extras); - } + String passphrase = getCachedPassphrase(secretKeyId); // if (signedOnly) { // resultData = PgpMain.verifyText(this, this, inputData, outStream, @@ -202,12 +218,14 @@ public class CryptoService extends Service { public void encrypt(final byte[] inputBytes, final String[] encryptionUserIds, final ICryptoCallback callback) throws RemoteException { + final AppSettings settings = getAppSettings(); + Runnable r = new Runnable() { @Override public void run() { try { - encryptSafe(inputBytes, encryptionUserIds, callback); + encryptSafe(inputBytes, encryptionUserIds, settings, callback); } catch (RemoteException e) { Log.e(Constants.TAG, "CryptoService", e); } @@ -330,6 +348,23 @@ public class CryptoService extends Service { return false; } + private AppSettings getAppSettings() { + String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); + + // is calling package allowed to use this service? + for (int i = 0; i < callingPackages.length; i++) { + String currentPkg = callingPackages[i]; + + Uri uri = KeychainContract.ApiApps.buildByPackageNameUri(currentPkg); + + AppSettings settings = ProviderHelper.getApiAppSettings(this, uri); + + return settings; + } + + return null; + } + /** * Checks if packageName is a registered app for the API. * diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 6a4c8a0af..343e5fbc3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -178,7 +178,7 @@ public class PassphraseCacheService extends Service { } masterKeyId = masterKey.getKeyID(); } - Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId" + masterKeyId); + Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId); // get cached passphrase String cachedPassphrase = mPassphraseCache.get(masterKeyId); -- cgit v1.2.3