session-android/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java
Moxie Marlinspike c2dcf7ae74 Refactor MasterSecret initialization, access, and timeout paths.
1) Consolidate all of the KeyCachingService interaction into a single
   mixin. Activities extend delegates which call through to the mixin.

2) Switch Activity increment/decrement triggers from onStop to onPause
   in order to account for some screen locks that don't stop activities.
2013-02-10 17:30:51 -08:00

129 lines
4.2 KiB
Java

package org.thoughtcrime.securesms;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.service.KeyCachingService;
public class PassphraseRequiredMixin {
private KeyCachingServiceConnection serviceConnection;
private BroadcastReceiver clearKeyReceiver;
private BroadcastReceiver newKeyReceiver;
public void onCreate(Context context, PassphraseRequiredActivity activity) {
initializeClearKeyReceiver(context, activity);
}
public void onResume(Context context, PassphraseRequiredActivity activity) {
initializeNewKeyReceiver(context, activity);
initializeServiceConnection(context, activity);
KeyCachingService.registerPassphraseActivityStarted(context);
}
public void onPause(Context context, PassphraseRequiredActivity activity) {
removeNewKeyReceiver(context);
removeServiceConnection(context);
KeyCachingService.registerPassphraseActivityStopped(context);
}
public void onDestroy(Context context, PassphraseRequiredActivity activity) {
removeClearKeyReceiver(context);
}
private void initializeClearKeyReceiver(Context context, final PassphraseRequiredActivity activity) {
this.clearKeyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
activity.onMasterSecretCleared();
}
};
IntentFilter filter = new IntentFilter(KeyCachingService.CLEAR_KEY_EVENT);
context.registerReceiver(clearKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private void initializeNewKeyReceiver(Context context, final PassphraseRequiredActivity activity) {
this.newKeyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
activity.onNewMasterSecret((MasterSecret)intent.getParcelableExtra("master_secret"));
}
};
IntentFilter filter = new IntentFilter(KeyCachingService.NEW_KEY_EVENT);
context.registerReceiver(newKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private void initializeServiceConnection(Context context, PassphraseRequiredActivity activity) {
Intent cachingIntent = new Intent(context, KeyCachingService.class);
context.startService(cachingIntent);
this.serviceConnection = new KeyCachingServiceConnection(activity);
Intent bindIntent = new Intent(context, KeyCachingService.class);
context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void removeClearKeyReceiver(Context context) {
if (clearKeyReceiver != null) {
context.unregisterReceiver(clearKeyReceiver);
clearKeyReceiver = null;
}
}
private void removeNewKeyReceiver(Context context) {
if (newKeyReceiver != null) {
context.unregisterReceiver(newKeyReceiver);
newKeyReceiver = null;
}
}
private void removeServiceConnection(Context context) {
if (this.serviceConnection != null && this.serviceConnection.isBound()) {
context.unbindService(this.serviceConnection);
}
}
private static class KeyCachingServiceConnection implements ServiceConnection {
private final PassphraseRequiredActivity activity;
private boolean isBound;
public KeyCachingServiceConnection(PassphraseRequiredActivity activity) {
this.activity = activity;
this.isBound = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
KeyCachingService keyCachingService = ((KeyCachingService.KeyCachingBinder)service).getService();
MasterSecret masterSecret = keyCachingService.getMasterSecret();
this.isBound = true;
if (masterSecret == null) {
activity.onMasterSecretCleared();
} else {
activity.onNewMasterSecret(masterSecret);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
this.isBound = false;
}
public boolean isBound() {
return this.isBound;
}
}
}