mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Merge branch '210-support-panic-kit-purge' into 'master'
Support for Destructive Panic Actions This MR is based on and requires !52. More details are available in the commit message. All known issues have now been fixed by new upstream releases. See merge request !54
This commit is contained in:
@@ -194,6 +194,11 @@
|
||||
<activity
|
||||
android:name=".android.panic.PanicPreferencesActivity"
|
||||
android:label="@string/panic_setting" >
|
||||
<intent-filter>
|
||||
<action android:name="info.guardianproject.panic.action.CONNECT" />
|
||||
<action android:name="info.guardianproject.panic.action.DISCONNECT" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.panic.PanicResponderActivity"
|
||||
|
||||
@@ -17,6 +17,7 @@ dependencies {
|
||||
compile "com.android.support:preference-v14:23.1.1"
|
||||
compile "com.android.support:design:23.1.1"
|
||||
compile "info.guardianproject.panic:panic:0.5"
|
||||
compile "info.guardianproject.trustedintents:trustedintents:0.2"
|
||||
}
|
||||
|
||||
dependencyVerification {
|
||||
@@ -29,6 +30,7 @@ dependencyVerification {
|
||||
'com.android.support:support-annotations:f347a35b9748a4103b39a6714a77e2100f488d623fd6268e259c177b200e9d82',
|
||||
'com.android.support:recyclerview-v7:7606373da0931a1e62588335465a0e390cd676c98117edab29220317495faefd',
|
||||
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
|
||||
'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -8,4 +8,22 @@
|
||||
android:summary="@string/lock_setting_summary"
|
||||
android:defaultValue="true"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="Destructive Actions">
|
||||
|
||||
<ListPreference
|
||||
android:key="pref_key_panic_app"
|
||||
android:title="@string/panic_app_setting_title"
|
||||
android:summary="@string/panic_app_setting_summary"
|
||||
android:icon="@android:drawable/ic_menu_close_clear_cancel"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_key_purge"
|
||||
android:title="@string/purge_setting_title"
|
||||
android:summary="@string/purge_setting_summary"
|
||||
android:enabled="false"
|
||||
android:defaultValue="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1,14 +1,240 @@
|
||||
package org.briarproject.android.panic;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.CheckBoxPreference;
|
||||
import android.support.v7.preference.ListPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.briarproject.R;
|
||||
|
||||
public class PanicPreferencesFragment extends PreferenceFragmentCompat {
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
|
||||
public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PanicPreferencesFragment.class.getName());
|
||||
|
||||
private PackageManager pm;
|
||||
private CheckBoxPreference lockPref;
|
||||
private ListPreference panicAppPref;
|
||||
private CheckBoxPreference purgePref;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle bundle, String s) {
|
||||
addPreferencesFromResource(R.xml.panic_preferences);
|
||||
|
||||
pm = getActivity().getPackageManager();
|
||||
|
||||
lockPref = (CheckBoxPreference) findPreference("pref_key_lock");
|
||||
panicAppPref = (ListPreference) findPreference("pref_key_panic_app");
|
||||
purgePref = (CheckBoxPreference) findPreference("pref_key_purge");
|
||||
|
||||
// check for connect/disconnect intents from panic trigger apps
|
||||
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
||||
LOG.info("Received DISCONNECT intent from Panic Trigger App.");
|
||||
// the necessary action should have been performed by the check
|
||||
getActivity().finish();
|
||||
} else {
|
||||
// check if we got a connect intent from a not yet connected app
|
||||
String packageName =
|
||||
PanicResponder.getConnectIntentSender(getActivity());
|
||||
if (!TextUtils.isEmpty((packageName)) &&
|
||||
!TextUtils.equals(packageName,
|
||||
PanicResponder
|
||||
.getTriggerPackageName(getActivity()))) {
|
||||
|
||||
// A new panic trigger app asks us to connect
|
||||
LOG.info("Received CONNECT intent from new Panic Trigger App.");
|
||||
|
||||
// Show dialog allowing the user to opt-in
|
||||
showOptInDialog();
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<CharSequence> entries = new ArrayList<CharSequence>();
|
||||
ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>();
|
||||
entries.add(0, getString(R.string.panic_app_setting_none));
|
||||
entryValues.add(0, Panic.PACKAGE_NAME_NONE);
|
||||
|
||||
for (ResolveInfo resolveInfo : PanicResponder.resolveTriggerApps(pm)) {
|
||||
if (resolveInfo.activityInfo == null)
|
||||
continue;
|
||||
entries.add(resolveInfo.activityInfo.loadLabel(pm));
|
||||
entryValues.add(resolveInfo.activityInfo.packageName);
|
||||
}
|
||||
|
||||
panicAppPref.setEntries(
|
||||
entries.toArray(new CharSequence[entries.size()]));
|
||||
panicAppPref.setEntryValues(
|
||||
entryValues.toArray(new CharSequence[entryValues.size()]));
|
||||
panicAppPref.setDefaultValue(Panic.PACKAGE_NAME_NONE);
|
||||
|
||||
panicAppPref.setOnPreferenceChangeListener(
|
||||
new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference,
|
||||
Object newValue) {
|
||||
String packageName = (String) newValue;
|
||||
PanicResponder.setTriggerPackageName(getActivity(),
|
||||
packageName);
|
||||
showPanicApp(packageName);
|
||||
|
||||
if (packageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||
purgePref.setChecked(false);
|
||||
purgePref.setEnabled(false);
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
} else {
|
||||
purgePref.setEnabled(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (entries.size() <= 1) {
|
||||
panicAppPref.setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(
|
||||
Preference preference) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(
|
||||
"market://details?id=info.guardianproject.ripple"));
|
||||
getActivity().startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getPreferenceScreen().getSharedPreferences()
|
||||
.registerOnSharedPreferenceChangeListener(this);
|
||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
getPreferenceScreen().getSharedPreferences()
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
// enable locking if purging gets enabled
|
||||
if (key.equals("pref_key_purge")
|
||||
&& sharedPreferences.getBoolean("pref_key_purge", false)) {
|
||||
lockPref.setChecked(true);
|
||||
}
|
||||
// disable purging if locking gets disabled
|
||||
if (key.equals("pref_key_lock")
|
||||
&& !sharedPreferences.getBoolean("pref_key_lock", true)
|
||||
&& sharedPreferences.getBoolean("pref_key_purge", false)) {
|
||||
purgePref.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void showPanicApp(String triggerPackageName) {
|
||||
if (TextUtils.isEmpty(triggerPackageName)
|
||||
|| triggerPackageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||
// no panic app set
|
||||
panicAppPref.setValue(Panic.PACKAGE_NAME_NONE);
|
||||
panicAppPref
|
||||
.setSummary(getString(R.string.panic_app_setting_summary));
|
||||
panicAppPref.setIcon(
|
||||
android.R.drawable.ic_menu_close_clear_cancel);
|
||||
purgePref.setEnabled(false);
|
||||
} else {
|
||||
// display connected panic app
|
||||
try {
|
||||
panicAppPref.setValue(triggerPackageName);
|
||||
panicAppPref.setSummary(pm.getApplicationLabel(
|
||||
pm.getApplicationInfo(triggerPackageName, 0)));
|
||||
panicAppPref.setIcon(
|
||||
pm.getApplicationIcon(triggerPackageName));
|
||||
purgePref.setEnabled(true);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// revert back to no app, just to be safe
|
||||
PanicResponder.setTriggerPackageName(getActivity(),
|
||||
Panic.PACKAGE_NAME_NONE);
|
||||
showPanicApp(Panic.PACKAGE_NAME_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showOptInDialog() {
|
||||
DialogInterface.OnClickListener okListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
PanicResponder.setTriggerPackageName(getActivity());
|
||||
showPanicApp(PanicResponder
|
||||
.getTriggerPackageName(getActivity()));
|
||||
getActivity().setResult(Activity.RESULT_OK);
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener cancelListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder =
|
||||
new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(
|
||||
getString(R.string.dialog_title_connect_panic_app));
|
||||
|
||||
CharSequence app = getString(R.string.unknown_app);
|
||||
String packageName = getCallingPackageName();
|
||||
if (packageName != null) {
|
||||
try {
|
||||
app = pm.getApplicationLabel(
|
||||
pm.getApplicationInfo(packageName, 0));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LOG.warning(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
String text = String.format(
|
||||
getString(R.string.dialog_message_connect_panic_app), app);
|
||||
builder.setMessage(text);
|
||||
builder.setPositiveButton(android.R.string.ok, okListener);
|
||||
builder.setNegativeButton(android.R.string.cancel, cancelListener);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private String getCallingPackageName() {
|
||||
ComponentName componentName = getActivity().getCallingActivity();
|
||||
String packageName = null;
|
||||
if (componentName != null) {
|
||||
packageName = componentName.getPackageName();
|
||||
}
|
||||
return packageName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,25 +7,78 @@ import android.os.Bundle;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import org.briarproject.android.BriarActivity;
|
||||
import org.briarproject.api.db.DatabaseConfig;
|
||||
import org.briarproject.util.FileUtils;
|
||||
import org.iilab.IilabEngineeringRSA2048Pin;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.guardianproject.GuardianProjectRSA4096;
|
||||
import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
import info.guardianproject.trustedintents.TrustedIntents;
|
||||
|
||||
public class PanicResponderActivity extends BriarActivity {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PanicResponderActivity.class.getName());
|
||||
@Inject private DatabaseConfig databaseConfig;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SharedPreferences sharedPref = PreferenceManager
|
||||
.getDefaultSharedPreferences(this);
|
||||
TrustedIntents trustedIntents = TrustedIntents.get(this);
|
||||
// Guardian Project Ripple
|
||||
trustedIntents.addTrustedSigner(GuardianProjectRSA4096.class);
|
||||
// Amnesty International's Panic Button, made by iilab.org
|
||||
trustedIntents.addTrustedSigner(IilabEngineeringRSA2048Pin.class);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && sharedPref.getBoolean("pref_key_lock", true)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
Intent intent = trustedIntents.getIntentFromTrustedSender(this);
|
||||
if (intent != null) {
|
||||
// received intent from trusted app
|
||||
if (Panic.isTriggerIntent(intent)) {
|
||||
SharedPreferences sharedPref = PreferenceManager
|
||||
.getDefaultSharedPreferences(this);
|
||||
|
||||
LOG.info("Received Panic Trigger...");
|
||||
|
||||
if (PanicResponder.receivedTriggerFromConnectedApp(this)) {
|
||||
LOG.info("Panic Trigger came from connected app.");
|
||||
LOG.info("Performing destructive responses...");
|
||||
|
||||
// Performing destructive panic responses
|
||||
if (sharedPref.getBoolean("pref_key_purge", false)) {
|
||||
LOG.info("Purging all data...");
|
||||
deleteAllData();
|
||||
}
|
||||
// still sign out if enabled
|
||||
else if (sharedPref.getBoolean("pref_key_lock", true)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
|
||||
// TODO add other panic behavior such as:
|
||||
// * send a pre-defined message to certain contacts (#212)
|
||||
// * uninstall the app (#211)
|
||||
|
||||
}
|
||||
// Performing non-destructive default panic response
|
||||
else if (sharedPref.getBoolean("pref_key_lock", true)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// received intent from non-trusted app
|
||||
else {
|
||||
intent = getIntent();
|
||||
if (intent != null && Panic.isTriggerIntent(intent)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
@@ -34,4 +87,23 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteAllData() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO somehow delete/shred the database more thoroughly
|
||||
FileUtils
|
||||
.deleteFileOrDir(
|
||||
databaseConfig.getDatabaseDirectory());
|
||||
clearSharedPrefs();
|
||||
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
|
||||
|
||||
// nothing left to do after everything is deleted,
|
||||
// so still sign out
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user