2018-02-13 21:17:21 +01:00
|
|
|
package me.impy.aegis.ui;
|
2018-02-09 17:31:07 +01:00
|
|
|
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.support.v7.app.ActionBar;
|
|
|
|
import android.support.v7.app.AlertDialog;
|
|
|
|
import android.support.v7.widget.LinearLayoutManager;
|
|
|
|
import android.support.v7.widget.RecyclerView;
|
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import javax.crypto.Cipher;
|
|
|
|
|
2018-02-13 21:17:21 +01:00
|
|
|
import me.impy.aegis.R;
|
2018-02-10 17:20:41 +01:00
|
|
|
import me.impy.aegis.crypto.KeyStoreHandle;
|
2018-02-13 19:27:40 +01:00
|
|
|
import me.impy.aegis.crypto.KeyStoreHandleException;
|
2018-02-09 17:31:07 +01:00
|
|
|
import me.impy.aegis.crypto.MasterKey;
|
2018-02-13 21:17:21 +01:00
|
|
|
import me.impy.aegis.db.slots.FingerprintSlot;
|
|
|
|
import me.impy.aegis.db.slots.PasswordSlot;
|
|
|
|
import me.impy.aegis.db.slots.Slot;
|
2018-06-06 19:38:13 +02:00
|
|
|
import me.impy.aegis.db.slots.SlotList;
|
2018-03-19 18:00:53 +01:00
|
|
|
import me.impy.aegis.db.slots.SlotException;
|
2018-02-09 17:31:07 +01:00
|
|
|
import me.impy.aegis.helpers.FingerprintHelper;
|
2018-05-14 21:02:35 +02:00
|
|
|
import me.impy.aegis.ui.dialogs.Dialogs;
|
2018-02-13 21:17:21 +01:00
|
|
|
import me.impy.aegis.ui.dialogs.FingerprintDialogFragment;
|
|
|
|
import me.impy.aegis.ui.views.SlotAdapter;
|
|
|
|
import me.impy.aegis.ui.dialogs.SlotDialogFragment;
|
2018-02-09 17:31:07 +01:00
|
|
|
|
|
|
|
public class SlotManagerActivity extends AegisActivity implements SlotAdapter.Listener, SlotDialogFragment.Listener {
|
|
|
|
private MasterKey _masterKey;
|
2018-06-06 19:38:13 +02:00
|
|
|
private SlotList _slots;
|
2018-02-09 17:31:07 +01:00
|
|
|
private SlotAdapter _adapter;
|
|
|
|
|
2018-06-09 20:23:39 +02:00
|
|
|
private boolean _edited;
|
2018-05-14 21:02:35 +02:00
|
|
|
|
2018-02-09 17:31:07 +01:00
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.activity_slots);
|
2018-06-09 20:23:39 +02:00
|
|
|
_edited = false;
|
2018-05-11 15:12:36 +02:00
|
|
|
|
2018-02-09 17:31:07 +01:00
|
|
|
ActionBar bar = getSupportActionBar();
|
|
|
|
bar.setHomeAsUpIndicator(R.drawable.ic_close);
|
|
|
|
bar.setDisplayHomeAsUpEnabled(true);
|
|
|
|
|
2018-02-10 17:20:41 +01:00
|
|
|
findViewById(R.id.button_add_fingerprint).setOnClickListener(view -> {
|
|
|
|
FingerprintDialogFragment dialog = new FingerprintDialogFragment();
|
|
|
|
dialog.show(getSupportFragmentManager(), null);
|
|
|
|
});
|
2018-02-09 17:31:07 +01:00
|
|
|
|
|
|
|
// set up the recycler view
|
|
|
|
_adapter = new SlotAdapter(this);
|
|
|
|
RecyclerView slotsView = findViewById(R.id.list_slots);
|
|
|
|
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
|
|
|
slotsView.setLayoutManager(layoutManager);
|
|
|
|
slotsView.setAdapter(_adapter);
|
|
|
|
slotsView.setNestedScrollingEnabled(false);
|
|
|
|
|
|
|
|
// load the slots and masterKey
|
|
|
|
_masterKey = (MasterKey) getIntent().getSerializableExtra("masterKey");
|
2018-06-06 19:38:13 +02:00
|
|
|
_slots = (SlotList) getIntent().getSerializableExtra("slots");
|
2018-02-09 17:31:07 +01:00
|
|
|
for (Slot slot : _slots) {
|
|
|
|
_adapter.addSlot(slot);
|
|
|
|
}
|
2018-02-10 17:20:41 +01:00
|
|
|
|
|
|
|
updateFingerprintButton();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateFingerprintButton() {
|
|
|
|
// only show the fingerprint option if we can get an instance of the fingerprint manager
|
|
|
|
// and if none of the slots in the collection has a matching alias in the keystore
|
|
|
|
int visibility = View.VISIBLE;
|
2018-02-13 19:27:40 +01:00
|
|
|
if (FingerprintHelper.isSupported()) {
|
|
|
|
try {
|
|
|
|
KeyStoreHandle keyStore = new KeyStoreHandle();
|
|
|
|
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
|
2018-03-13 18:30:47 +01:00
|
|
|
if (keyStore.containsKey(slot.getUUID().toString()) && FingerprintHelper.getManager(this) != null) {
|
2018-02-13 19:27:40 +01:00
|
|
|
visibility = View.GONE;
|
|
|
|
break;
|
|
|
|
}
|
2018-02-10 17:20:41 +01:00
|
|
|
}
|
2018-02-13 19:27:40 +01:00
|
|
|
} catch (KeyStoreHandleException e) {
|
|
|
|
visibility = View.GONE;
|
2018-02-10 17:20:41 +01:00
|
|
|
}
|
2018-02-13 19:27:40 +01:00
|
|
|
} else {
|
2018-02-10 17:20:41 +01:00
|
|
|
visibility = View.GONE;
|
|
|
|
}
|
|
|
|
findViewById(R.id.button_add_fingerprint).setVisibility(visibility);
|
2018-02-09 17:31:07 +01:00
|
|
|
}
|
|
|
|
|
2018-05-14 21:02:35 +02:00
|
|
|
private void onSave() {
|
2018-02-09 17:31:07 +01:00
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.putExtra("slots", _slots);
|
|
|
|
setResult(RESULT_OK, intent);
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case android.R.id.home:
|
|
|
|
onBackPressed();
|
2018-05-14 21:02:35 +02:00
|
|
|
break;
|
2018-02-09 17:31:07 +01:00
|
|
|
case R.id.action_save:
|
2018-05-14 21:02:35 +02:00
|
|
|
onSave();
|
|
|
|
break;
|
2018-02-09 17:31:07 +01:00
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
2018-05-14 21:02:35 +02:00
|
|
|
|
|
|
|
return true;
|
2018-02-09 17:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
|
getMenuInflater().inflate(R.menu.menu_slots, menu);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-14 21:02:35 +02:00
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
|
|
|
if (!_edited) {
|
|
|
|
super.onBackPressed();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dialogs.showDiscardDialog(this,
|
|
|
|
(dialog, which) -> onSave(),
|
|
|
|
(dialog, which) -> super.onBackPressed()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-02-09 17:31:07 +01:00
|
|
|
@Override
|
|
|
|
public void onEditSlot(Slot slot) {
|
2018-02-13 13:29:01 +01:00
|
|
|
/*EditText textName = new EditText(this);
|
2018-02-09 17:31:07 +01:00
|
|
|
textName.setHint("Name");
|
|
|
|
|
|
|
|
new AlertDialog.Builder(this)
|
|
|
|
.setTitle("Edit slot name")
|
|
|
|
.setView(textName)
|
|
|
|
.setPositiveButton(android.R.string.ok, (dialog, whichButton) -> {
|
|
|
|
String name = textName.getText().toString();
|
2018-05-14 21:02:35 +02:00
|
|
|
_edited = true;
|
2018-02-09 17:31:07 +01:00
|
|
|
})
|
|
|
|
.setNegativeButton(android.R.string.cancel, null)
|
2018-02-13 13:29:01 +01:00
|
|
|
.show();*/
|
2018-02-09 17:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRemoveSlot(Slot slot) {
|
|
|
|
if (slot instanceof PasswordSlot && _slots.findAll(PasswordSlot.class).size() <= 1) {
|
|
|
|
Toast.makeText(this, "You must have at least one password slot", Toast.LENGTH_SHORT).show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
new AlertDialog.Builder(this)
|
|
|
|
.setTitle("Remove slot")
|
|
|
|
.setMessage("Are you sure you want to remove this slot?")
|
|
|
|
.setPositiveButton(android.R.string.yes, (dialog, whichButton) -> {
|
|
|
|
_slots.remove(slot);
|
|
|
|
_adapter.removeSlot(slot);
|
2018-05-14 21:02:35 +02:00
|
|
|
_edited = true;
|
2018-02-10 17:20:41 +01:00
|
|
|
updateFingerprintButton();
|
2018-02-09 17:31:07 +01:00
|
|
|
})
|
|
|
|
.setNegativeButton(android.R.string.no, null)
|
|
|
|
.show();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSlotResult(Slot slot, Cipher cipher) {
|
|
|
|
try {
|
2018-06-06 19:38:13 +02:00
|
|
|
slot.setKey(_masterKey, cipher);
|
2018-03-19 18:00:53 +01:00
|
|
|
} catch (SlotException e) {
|
2018-02-09 17:31:07 +01:00
|
|
|
onException(e);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-10 17:20:41 +01:00
|
|
|
|
2018-02-09 17:31:07 +01:00
|
|
|
_slots.add(slot);
|
|
|
|
_adapter.addSlot(slot);
|
2018-05-14 21:02:35 +02:00
|
|
|
_edited = true;
|
2018-02-10 17:20:41 +01:00
|
|
|
updateFingerprintButton();
|
2018-02-09 17:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onException(Exception e) {
|
|
|
|
Toast.makeText(this, "An error occurred while trying to add a new slot: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
|
|
}
|
|
|
|
}
|