panic: uninstall apps based destructive panic trigger

This will uninstall the list of apps that the user has setup in the Panic
Settings if Privileged Extension is installed.  This also requires that the
user set up a trusted connection between a panic trigger app (e.g. Ripple)
and F-Droid.
This commit is contained in:
Hans-Christoph Steiner 2019-05-29 17:20:09 +02:00
parent d762e187dc
commit 72f5398b79

View File

@ -1,17 +1,41 @@
package org.fdroid.fdroid.views.panic;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.views.hiding.HidingManager;
import info.guardianproject.panic.Panic;
import info.guardianproject.panic.PanicResponder;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.InstalledApp;
import org.fdroid.fdroid.data.InstalledAppProvider;
import org.fdroid.fdroid.installer.Installer;
import org.fdroid.fdroid.installer.InstallerService;
import org.fdroid.fdroid.installer.PrivilegedInstaller;
import org.fdroid.fdroid.views.hiding.HidingManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* This {@link Activity} is purely to run events in response to a panic trigger.
* It needs to be an {@code Activity} rather than a {@link android.app.Service}
* so that it can fetch some of the required information about what sent the
* {@link Intent}. This is therefore an {@code Activity} without any UI, which
* is a special case in Android. All the code must be in
* {@link #onCreate(Bundle)} and {@link #finish()} must be called at the end of
* that method.
*
* @see PanicResponder#receivedTriggerFromConnectedApp(Activity)
*/
public class PanicResponderActivity extends AppCompatActivity {
private static final String TAG = PanicResponderActivity.class.getSimpleName();
@ -29,12 +53,65 @@ public class PanicResponderActivity extends AppCompatActivity {
// received intent from panic app
Log.i(TAG, "Received Panic Trigger...");
Preferences preferences = Preferences.get();
final Preferences preferences = Preferences.get();
if (PanicResponder.receivedTriggerFromConnectedApp(this)) {
Log.i(TAG, "Panic Trigger came from connected app");
boolean receivedTriggerFromConnectedApp = PanicResponder.receivedTriggerFromConnectedApp(this);
final boolean runningAppUninstalls = PrivilegedInstaller.isDefault(this);
// Performing destructive panic responses
ArrayList<String> wipeList = new ArrayList<>(preferences.getPanicWipeSet());
preferences.setPanicWipeSet(Collections.<String>emptySet());
preferences.setPanicTmpSelectedSet(Collections.<String>emptySet());
if (receivedTriggerFromConnectedApp && runningAppUninstalls && wipeList.size() > 0) {
// if this app (e.g. F-Droid) is to be deleted, do it last
if (wipeList.contains(getPackageName())) {
wipeList.remove(getPackageName());
wipeList.add(getPackageName());
}
final Context context = this;
final CountDownLatch latch = new CountDownLatch(1);
final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
final String lastToUninstall = wipeList.get(wipeList.size() - 1);
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch ((intent.getAction())) {
case Installer.ACTION_UNINSTALL_INTERRUPTED:
case Installer.ACTION_UNINSTALL_COMPLETE:
latch.countDown();
break;
}
}
};
lbm.registerReceiver(receiver, Installer.getUninstallIntentFilter(lastToUninstall));
for (String packageName : wipeList) {
InstalledApp installedApp = InstalledAppProvider.Helper.findByPackageName(context, packageName);
InstallerService.uninstall(context, new Apk(installedApp));
}
// wait for apps to uninstall before triggering final responses
new Thread() {
@Override
public void run() {
try {
latch.await(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
// ignored
}
lbm.unregisterReceiver(receiver);
if (preferences.panicHide()) {
HidingManager.hide(context);
}
if (preferences.panicExit()) {
exitAndClear();
}
}
}.start();
} else if (receivedTriggerFromConnectedApp) {
// Performing destructive panic response
if (preferences.panicHide()) {
Log.i(TAG, "Hiding app...");
HidingManager.hide(this);
@ -42,13 +119,16 @@ public class PanicResponderActivity extends AppCompatActivity {
}
// exit and clear, if not deactivated
if (preferences.panicExit()) {
ExitActivity.exitAndRemoveFromRecentApps(this);
if (Build.VERSION.SDK_INT >= 21) {
finishAndRemoveTask();
}
if (!runningAppUninstalls && preferences.panicExit()) {
exitAndClear();
}
finish();
}
private void exitAndClear() {
ExitActivity.exitAndRemoveFromRecentApps(this);
if (Build.VERSION.SDK_INT >= 21) {
finishAndRemoveTask();
}
}
}