mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-14 12:55:08 -05:00
IMplement CryptoInputParcelCacheService
This commit is contained in:
parent
9fc001c9b9
commit
256d644d03
@ -696,6 +696,10 @@
|
||||
android:name=".service.PassphraseCacheService"
|
||||
android:exported="false"
|
||||
android:process=":passphrase_cache" />
|
||||
<service
|
||||
android:name=".remote.CryptoInputParcelCacheService"
|
||||
android:exported="false"
|
||||
android:process=":remote_api" />
|
||||
<service
|
||||
android:name=".service.KeychainIntentService"
|
||||
android:exported="false" />
|
||||
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.remote;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class CryptoInputParcelCacheService extends Service {
|
||||
|
||||
public static final String ACTION_ADD = Constants.INTENT_PREFIX + "ADD";
|
||||
public static final String ACTION_GET = Constants.INTENT_PREFIX + "GET";
|
||||
|
||||
public static final String EXTRA_CRYPTO_INPUT_PARCEL = "crypto_input_parcel";
|
||||
public static final String EXTRA_UUID1 = "uuid1";
|
||||
public static final String EXTRA_UUID2 = "uuid2";
|
||||
public static final String EXTRA_MESSENGER = "messenger";
|
||||
|
||||
private static final int MSG_GET_OKAY = 1;
|
||||
private static final int MSG_GET_NOT_FOUND = 2;
|
||||
|
||||
Context mContext;
|
||||
|
||||
private static final UUID NULL_UUID = new UUID(0, 0);
|
||||
|
||||
private ConcurrentHashMap<UUID, CryptoInputParcel> mCache = new ConcurrentHashMap<>();
|
||||
|
||||
public static class InputParcelNotFound extends Exception {
|
||||
public InputParcelNotFound() {
|
||||
}
|
||||
|
||||
public InputParcelNotFound(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addCryptoInputParcel(Context context, Intent data, CryptoInputParcel inputParcel) {
|
||||
UUID mTicket = addCryptoInputParcel(context, inputParcel);
|
||||
// And write out the UUID most and least significant bits.
|
||||
data.putExtra(OpenPgpApi.EXTRA_CALL_UUID1, mTicket.getMostSignificantBits());
|
||||
data.putExtra(OpenPgpApi.EXTRA_CALL_UUID2, mTicket.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public static CryptoInputParcel getCryptoInputParcel(Context context, Intent data) {
|
||||
if (!data.getExtras().containsKey(OpenPgpApi.EXTRA_CALL_UUID1)
|
||||
|| !data.getExtras().containsKey(OpenPgpApi.EXTRA_CALL_UUID2)) {
|
||||
return null;
|
||||
}
|
||||
long mostSig = data.getLongExtra(OpenPgpApi.EXTRA_CALL_UUID1, 0);
|
||||
long leastSig = data.getLongExtra(OpenPgpApi.EXTRA_CALL_UUID2, 0);
|
||||
UUID uuid = new UUID(mostSig, leastSig);
|
||||
try {
|
||||
return getCryptoInputParcel(context, uuid);
|
||||
} catch (InputParcelNotFound inputParcelNotFound) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID addCryptoInputParcel(Context context, CryptoInputParcel inputParcel) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
Intent intent = new Intent(context, CryptoInputParcelCacheService.class);
|
||||
intent.setAction(ACTION_ADD);
|
||||
intent.putExtra(EXTRA_CRYPTO_INPUT_PARCEL, inputParcel);
|
||||
intent.putExtra(EXTRA_UUID1, uuid.getMostSignificantBits());
|
||||
intent.putExtra(EXTRA_UUID2, uuid.getLeastSignificantBits());
|
||||
context.startService(intent);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
private static CryptoInputParcel getCryptoInputParcel(Context context, UUID uuid) throws InputParcelNotFound {
|
||||
Intent intent = new Intent(context, CryptoInputParcelCacheService.class);
|
||||
intent.setAction(ACTION_GET);
|
||||
|
||||
final Object mutex = new Object();
|
||||
final Message returnMessage = Message.obtain();
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread("getParcelableThread");
|
||||
handlerThread.start();
|
||||
Handler returnHandler = new Handler(handlerThread.getLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
// copy over result to handle after mutex.wait
|
||||
returnMessage.what = message.what;
|
||||
returnMessage.copyFrom(message);
|
||||
synchronized (mutex) {
|
||||
mutex.notify();
|
||||
}
|
||||
// quit handlerThread
|
||||
getLooper().quit();
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
Messenger messenger = new Messenger(returnHandler);
|
||||
intent.putExtra(EXTRA_UUID1, uuid.getMostSignificantBits());
|
||||
intent.putExtra(EXTRA_UUID2, uuid.getLeastSignificantBits());
|
||||
intent.putExtra(EXTRA_MESSENGER, messenger);
|
||||
// send intent to this service
|
||||
context.startService(intent);
|
||||
|
||||
// Wait on mutex until parcelable is returned to handlerThread. Note that this local
|
||||
// variable is used in the handler closure above, so it does make sense here!
|
||||
// noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (mutex) {
|
||||
try {
|
||||
mutex.wait(3000);
|
||||
} catch (InterruptedException e) {
|
||||
// don't care
|
||||
}
|
||||
}
|
||||
|
||||
switch (returnMessage.what) {
|
||||
case MSG_GET_OKAY:
|
||||
Bundle returnData = returnMessage.getData();
|
||||
returnData.setClassLoader(context.getClassLoader());
|
||||
return returnData.getParcelable(EXTRA_CRYPTO_INPUT_PARCEL);
|
||||
case MSG_GET_NOT_FOUND:
|
||||
throw new InputParcelNotFound();
|
||||
default:
|
||||
Log.e(Constants.TAG, "timeout!");
|
||||
throw new InputParcelNotFound("should not happen!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed when service is started by intent
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
if (intent == null || intent.getAction() == null) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
String action = intent.getAction();
|
||||
switch (action) {
|
||||
case ACTION_ADD: {
|
||||
long uuid1 = intent.getLongExtra(EXTRA_UUID1, 0);
|
||||
long uuid2 = intent.getLongExtra(EXTRA_UUID2, 0);
|
||||
UUID uuid = new UUID(uuid1, uuid2);
|
||||
CryptoInputParcel inputParcel = intent.getParcelableExtra(EXTRA_CRYPTO_INPUT_PARCEL);
|
||||
mCache.put(uuid, inputParcel);
|
||||
|
||||
break;
|
||||
}
|
||||
case ACTION_GET: {
|
||||
long uuid1 = intent.getLongExtra(EXTRA_UUID1, 0);
|
||||
long uuid2 = intent.getLongExtra(EXTRA_UUID2, 0);
|
||||
UUID uuid = new UUID(uuid1, uuid2);
|
||||
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
||||
|
||||
Message msg = Message.obtain();
|
||||
// UUID.equals isn't well documented; we use compareTo instead.
|
||||
if (NULL_UUID.compareTo(uuid) == 0) {
|
||||
msg.what = MSG_GET_NOT_FOUND;
|
||||
} else {
|
||||
CryptoInputParcel inputParcel = mCache.get(uuid);
|
||||
mCache.remove(uuid);
|
||||
msg.what = MSG_GET_OKAY;
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(EXTRA_CRYPTO_INPUT_PARCEL, inputParcel);
|
||||
msg.setData(bundle);
|
||||
}
|
||||
|
||||
try {
|
||||
messenger.send(msg);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(Constants.TAG, "CryptoInputParcelCacheService: Sending message failed", e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Log.e(Constants.TAG, "CryptoInputParcelCacheService: Intent or Intent Action not supported!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCache.size() <= 0) {
|
||||
// stop whole service if cache is empty
|
||||
Log.d(Constants.TAG, "CryptoInputParcelCacheService: No passphrases remaining in memory, stopping service!");
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mContext = this;
|
||||
Log.d(Constants.TAG, "CryptoInputParcelCacheService, onCreate()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.d(Constants.TAG, "CryptoInputParcelCacheService, onDestroy()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
public class CryptoInputParcelCacheServiceBinder extends Binder {
|
||||
public CryptoInputParcelCacheService getService() {
|
||||
return CryptoInputParcelCacheService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private final IBinder mBinder = new CryptoInputParcelCacheServiceBinder();
|
||||
|
||||
}
|
@ -36,7 +36,6 @@ import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
|
||||
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpConstants;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
|
||||
@ -57,7 +56,6 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
|
||||
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ParcelableCache;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -68,25 +66,6 @@ import java.util.Set;
|
||||
|
||||
public class OpenPgpService extends RemoteService {
|
||||
|
||||
/**
|
||||
* Instead of parceling the CryptoInputParcel, they are cached on our side to prevent
|
||||
* leakage of passphrases, symmetric keys, an yubikey related pass-through values
|
||||
*/
|
||||
private static ParcelableCache<CryptoInputParcel> inputParcelCache;
|
||||
static {
|
||||
inputParcelCache = new ParcelableCache<>();
|
||||
}
|
||||
|
||||
public static void cacheCryptoInputParcel(Intent data, CryptoInputParcel inputParcel) {
|
||||
inputParcelCache.cacheAndWriteToIntent(inputParcel, data,
|
||||
OpenPgpApi.EXTRA_CALL_UUID1, OpenPgpApi.EXTRA_CALL_UUID2);
|
||||
}
|
||||
|
||||
public static CryptoInputParcel getCryptoInputParcel(Intent data) {
|
||||
return inputParcelCache.readFromIntentAndGetFromCache(data,
|
||||
OpenPgpApi.EXTRA_CALL_UUID1, OpenPgpApi.EXTRA_CALL_UUID2);
|
||||
}
|
||||
|
||||
static final String[] EMAIL_SEARCH_PROJECTION = new String[]{
|
||||
KeyRings._ID,
|
||||
KeyRings.MASTER_KEY_ID,
|
||||
@ -283,7 +262,7 @@ public class OpenPgpService extends RemoteService {
|
||||
long inputLength = is.available();
|
||||
InputData inputData = new InputData(is, inputLength);
|
||||
|
||||
CryptoInputParcel inputParcel = getCryptoInputParcel(data);
|
||||
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (inputParcel == null) {
|
||||
inputParcel = new CryptoInputParcel();
|
||||
}
|
||||
@ -424,7 +403,7 @@ public class OpenPgpService extends RemoteService {
|
||||
.setAdditionalEncryptId(signKeyId); // add sign key for encryption
|
||||
}
|
||||
|
||||
CryptoInputParcel inputParcel = getCryptoInputParcel(data);
|
||||
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (inputParcel == null) {
|
||||
inputParcel = new CryptoInputParcel();
|
||||
}
|
||||
@ -513,7 +492,7 @@ public class OpenPgpService extends RemoteService {
|
||||
this, new ProviderHelper(getContext()), null, inputData, os
|
||||
);
|
||||
|
||||
CryptoInputParcel inputParcel = getCryptoInputParcel(data);
|
||||
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
|
||||
if (inputParcel == null) {
|
||||
inputParcel = new CryptoInputParcel();
|
||||
}
|
||||
@ -768,9 +747,7 @@ public class OpenPgpService extends RemoteService {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: multi-threading
|
||||
private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
|
||||
|
||||
@Override
|
||||
public Intent execute(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) {
|
||||
try {
|
||||
@ -780,30 +757,42 @@ public class OpenPgpService extends RemoteService {
|
||||
}
|
||||
|
||||
String action = data.getAction();
|
||||
if (OpenPgpApi.ACTION_CLEARTEXT_SIGN.equals(action)) {
|
||||
return signImpl(data, input, output, true);
|
||||
} else if (OpenPgpApi.ACTION_SIGN.equals(action)) {
|
||||
// DEPRECATED: same as ACTION_CLEARTEXT_SIGN
|
||||
Log.w(Constants.TAG, "You are using a deprecated API call, please use ACTION_CLEARTEXT_SIGN instead of ACTION_SIGN!");
|
||||
return signImpl(data, input, output, true);
|
||||
} else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(action)) {
|
||||
return signImpl(data, input, output, false);
|
||||
} else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) {
|
||||
return encryptAndSignImpl(data, input, output, false);
|
||||
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
|
||||
return encryptAndSignImpl(data, input, output, true);
|
||||
} else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) {
|
||||
return decryptAndVerifyImpl(data, input, output, false);
|
||||
} else if (OpenPgpApi.ACTION_DECRYPT_METADATA.equals(action)) {
|
||||
return decryptAndVerifyImpl(data, input, output, true);
|
||||
} else if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(action)) {
|
||||
return getSignKeyIdImpl(data);
|
||||
} else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {
|
||||
return getKeyIdsImpl(data);
|
||||
} else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
|
||||
return getKeyImpl(data);
|
||||
} else {
|
||||
return null;
|
||||
switch (action) {
|
||||
case OpenPgpApi.ACTION_CLEARTEXT_SIGN: {
|
||||
return signImpl(data, input, output, true);
|
||||
}
|
||||
case OpenPgpApi.ACTION_SIGN: {
|
||||
// DEPRECATED: same as ACTION_CLEARTEXT_SIGN
|
||||
Log.w(Constants.TAG, "You are using a deprecated API call, please use ACTION_CLEARTEXT_SIGN instead of ACTION_SIGN!");
|
||||
return signImpl(data, input, output, true);
|
||||
}
|
||||
case OpenPgpApi.ACTION_DETACHED_SIGN: {
|
||||
return signImpl(data, input, output, false);
|
||||
}
|
||||
case OpenPgpApi.ACTION_ENCRYPT: {
|
||||
return encryptAndSignImpl(data, input, output, false);
|
||||
}
|
||||
case OpenPgpApi.ACTION_SIGN_AND_ENCRYPT: {
|
||||
return encryptAndSignImpl(data, input, output, true);
|
||||
}
|
||||
case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
|
||||
return decryptAndVerifyImpl(data, input, output, false);
|
||||
}
|
||||
case OpenPgpApi.ACTION_DECRYPT_METADATA: {
|
||||
return decryptAndVerifyImpl(data, input, output, true);
|
||||
}
|
||||
case OpenPgpApi.ACTION_GET_SIGN_KEY_ID: {
|
||||
return getSignKeyIdImpl(data);
|
||||
}
|
||||
case OpenPgpApi.ACTION_GET_KEY_IDS: {
|
||||
return getKeyIdsImpl(data);
|
||||
}
|
||||
case OpenPgpApi.ACTION_GET_KEY: {
|
||||
return getKeyImpl(data);
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// always close input and output file descriptors even in error cases
|
||||
|
@ -337,11 +337,17 @@ public class PassphraseCacheService extends Service {
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.d(Constants.TAG, "PassphraseCacheService.onStartCommand()");
|
||||
|
||||
if (intent == null || intent.getAction() == null) {
|
||||
updateService();
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
// register broadcastreceiver
|
||||
registerReceiver();
|
||||
|
||||
if (intent != null && intent.getAction() != null) {
|
||||
if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) {
|
||||
String action = intent.getAction();
|
||||
switch (action) {
|
||||
case ACTION_PASSPHRASE_CACHE_ADD: {
|
||||
long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL);
|
||||
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
|
||||
@ -365,9 +371,9 @@ public class PassphraseCacheService extends Service {
|
||||
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
||||
am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, referenceKeyId));
|
||||
}
|
||||
|
||||
updateService();
|
||||
} else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) {
|
||||
break;
|
||||
}
|
||||
case ACTION_PASSPHRASE_CACHE_GET: {
|
||||
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, Constants.key.symmetric);
|
||||
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, Constants.key.symmetric);
|
||||
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
|
||||
@ -395,7 +401,9 @@ public class PassphraseCacheService extends Service {
|
||||
} catch (RemoteException e) {
|
||||
Log.e(Constants.TAG, "PassphraseCacheService: Sending message failed", e);
|
||||
}
|
||||
} else if (ACTION_PASSPHRASE_CACHE_CLEAR.equals(intent.getAction())) {
|
||||
break;
|
||||
}
|
||||
case ACTION_PASSPHRASE_CACHE_CLEAR: {
|
||||
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
if (intent.hasExtra(EXTRA_SUBKEY_ID) && intent.hasExtra(EXTRA_KEY_ID)) {
|
||||
@ -419,13 +427,16 @@ public class PassphraseCacheService extends Service {
|
||||
mPassphraseCache.clear();
|
||||
|
||||
}
|
||||
|
||||
updateService();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Log.e(Constants.TAG, "PassphraseCacheService: Intent or Intent Action not supported!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateService();
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,11 @@ import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.remote.OpenPgpService;
|
||||
import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
@ -93,7 +91,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
|
||||
}
|
||||
|
||||
if (mServiceIntent != null) {
|
||||
OpenPgpService.cacheCryptoInputParcel(mServiceIntent, inputParcel);
|
||||
CryptoInputParcelCacheService.addCryptoInputParcel(this, mServiceIntent, inputParcel);
|
||||
setResult(RESULT_OK, mServiceIntent);
|
||||
} else {
|
||||
Intent result = new Intent();
|
||||
|
@ -41,7 +41,6 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
||||
@ -53,11 +52,10 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.remote.OpenPgpService;
|
||||
import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
@ -428,7 +426,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
|
||||
CryptoInputParcel inputParcel = new CryptoInputParcel(null, passphrase);
|
||||
if (mServiceIntent != null) {
|
||||
OpenPgpService.cacheCryptoInputParcel(mServiceIntent, inputParcel);
|
||||
CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent, inputParcel);
|
||||
getActivity().setResult(RESULT_OK, mServiceIntent);
|
||||
} else {
|
||||
// also return passphrase back to activity
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -30,7 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* To overcome this issue this class allows to cache Parcelables, mapped by unique UUIDs,
|
||||
* which are written to the parcel instead of the whole Parcelable.
|
||||
*/
|
||||
public class ParcelableCache<E extends Object> {
|
||||
public class ParcelableCache<E> {
|
||||
|
||||
private static final UUID NULL_UUID = new UUID(0, 0);
|
||||
|
||||
@ -39,7 +37,7 @@ public class ParcelableCache<E extends Object> {
|
||||
* This is used such that when we become parceled, we are
|
||||
* well below the 1 MB boundary that is specified.
|
||||
*/
|
||||
private ConcurrentHashMap<UUID, E> dehydratedLogs = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<UUID, E> objectCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Dehydrate a Parcelable (such that it is available after deparcelization)
|
||||
@ -52,9 +50,9 @@ public class ParcelableCache<E extends Object> {
|
||||
if (parcelable == null) {
|
||||
return NULL_UUID;
|
||||
} else {
|
||||
UUID ticket = UUID.randomUUID();
|
||||
dehydratedLogs.put(ticket, parcelable);
|
||||
return ticket;
|
||||
UUID uuid = UUID.randomUUID();
|
||||
objectCache.put(uuid, parcelable);
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,53 +61,34 @@ public class ParcelableCache<E extends Object> {
|
||||
* invalidating its place in the dehydration pool.
|
||||
* This is used such that when parcelized, the Parcelable is no larger than 1 MB.
|
||||
*
|
||||
* @param ticket A UUID ticket that identifies the log in question.
|
||||
* @param uuid A UUID ticket that identifies the log in question.
|
||||
* @return An OperationLog.
|
||||
*/
|
||||
private E rehydrateParcelable(UUID ticket) {
|
||||
private E rehydrateParcelable(UUID uuid) {
|
||||
// UUID.equals isn't well documented; we use compareTo instead.
|
||||
if (NULL_UUID.compareTo(ticket) == 0) {
|
||||
if (NULL_UUID.compareTo(uuid) == 0) {
|
||||
return null;
|
||||
} else {
|
||||
E parcelable = dehydratedLogs.get(ticket);
|
||||
dehydratedLogs.remove(ticket);
|
||||
E parcelable = objectCache.get(uuid);
|
||||
objectCache.remove(uuid);
|
||||
return parcelable;
|
||||
}
|
||||
}
|
||||
|
||||
public E readFromIntentAndGetFromCache(Intent data, String key1, String key2) {
|
||||
if (!data.getExtras().containsKey(key1) || !data.getExtras().containsKey(key2)) {
|
||||
return null;
|
||||
}
|
||||
long mostSig = data.getLongExtra(key1, 0);
|
||||
long leastSig = data.getLongExtra(key2, 0);
|
||||
UUID mTicket = new UUID(mostSig, leastSig);
|
||||
// fetch the dehydrated log out of storage (this removes it from the dehydration pool)
|
||||
return rehydrateParcelable(mTicket);
|
||||
}
|
||||
|
||||
public E readFromParcelAndGetFromCache(Parcel source) {
|
||||
long mostSig = source.readLong();
|
||||
long leastSig = source.readLong();
|
||||
UUID mTicket = new UUID(mostSig, leastSig);
|
||||
// fetch the dehydrated log out of storage (this removes it from the dehydration pool)
|
||||
// fetch the dehydrated parcelable out of storage (this removes it from the dehydration pool)
|
||||
return rehydrateParcelable(mTicket);
|
||||
}
|
||||
|
||||
public void cacheAndWriteToParcel(E parcelable, Parcel dest) {
|
||||
// Get a ticket for our log.
|
||||
// Get a ticket for our parcelable.
|
||||
UUID mTicket = dehydrateParcelable(parcelable);
|
||||
// And write out the UUID most and least significant bits.
|
||||
dest.writeLong(mTicket.getMostSignificantBits());
|
||||
dest.writeLong(mTicket.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public void cacheAndWriteToIntent(E parcelable, Intent data, String key1, String key2) {
|
||||
// Get a ticket for our log.
|
||||
UUID mTicket = dehydrateParcelable(parcelable);
|
||||
// And write out the UUID most and least significant bits.
|
||||
data.putExtra(key1, mTicket.getMostSignificantBits());
|
||||
data.putExtra(key2, mTicket.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user