Merge branch '1357-proper-panic-deletion' into 'master'

Stop lifecycle before deleting app data and exit cleanly

Closes #1380 and #1357

See merge request briar/briar!1060
This commit is contained in:
akwizgran
2019-03-19 14:15:49 +00:00
7 changed files with 65 additions and 25 deletions

View File

@@ -12,11 +12,15 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.util.IoUtils;
import java.io.File;
import java.util.HashSet;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
class AndroidAccountManager extends AccountManagerImpl
implements AccountManager {
@@ -89,20 +93,32 @@ class AndroidAccountManager extends AccountManagerImpl
LOG.warning("Could not clear shared preferences");
}
// Delete files, except lib and shared_prefs directories
HashSet<File> files = new HashSet<>();
File dataDir = new File(appContext.getApplicationInfo().dataDir);
File[] children = dataDir.listFiles();
if (children == null) {
@Nullable
File[] fileArray = dataDir.listFiles();
if (fileArray == null) {
LOG.warning("Could not list files in app data dir");
} else {
for (File child : children) {
String name = child.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
IoUtils.deleteFileOrDir(child);
}
files.addAll(asList(fileArray));
}
files.add(appContext.getFilesDir());
files.add(appContext.getCacheDir());
files.add(appContext.getExternalCacheDir());
if (SDK_INT >= 19) {
files.addAll(asList(appContext.getExternalCacheDirs()));
}
if (SDK_INT >= 21) {
files.addAll(asList(appContext.getExternalMediaDirs()));
}
for (File file : files) {
String name = file.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
IoUtils.deleteFileOrDir(file);
}
}
// Recreate the cache dir as some OpenGL drivers expect it to exist
if (!new File(dataDir, "cache").mkdir())
if (!new File(dataDir, "cache").mkdirs())
LOG.warning("Could not recreate cache dir");
}
}

View File

@@ -112,6 +112,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
// Other directories should be deleted
File potatoDir = new File(testDir, ".potato");
File potatoFile = new File(potatoDir, "file");
File filesDir = new File(testDir, "filesDir");
File externalCacheDir = new File(testDir, "externalCacheDir");
context.checking(new Expectations() {{
oneOf(prefs).edit();
@@ -128,6 +130,12 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(true));
oneOf(app).getApplicationInfo();
will(returnValue(applicationInfo));
oneOf(app).getFilesDir();
will(returnValue(filesDir));
oneOf(app).getCacheDir();
will(returnValue(cacheDir));
oneOf(app).getExternalCacheDir();
will(returnValue(externalCacheDir));
}});
assertTrue(dbDir.mkdirs());
@@ -140,6 +148,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertTrue(cacheFile.createNewFile());
assertTrue(potatoDir.mkdirs());
assertTrue(potatoFile.createNewFile());
assertTrue(filesDir.mkdirs());
assertTrue(externalCacheDir.mkdirs());
accountManager.deleteAccount();
@@ -153,6 +163,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(cacheFile.exists());
assertFalse(potatoDir.exists());
assertFalse(potatoFile.exists());
assertFalse(filesDir.exists());
assertFalse(externalCacheDir.exists());
}
@After

View File

@@ -185,13 +185,15 @@ public abstract class BriarActivity extends BaseActivity {
b.show();
}
protected void signOut(boolean removeFromRecentApps) {
protected void signOut(boolean removeFromRecentApps,
boolean deleteAccount) {
if (briarController.accountSignedIn()) {
// Don't use UiResultHandler because we want the result even if
// this activity has been destroyed
briarController.signOut(result -> runOnUiThread(
() -> exit(removeFromRecentApps)));
() -> exit(removeFromRecentApps)), deleteAccount);
} else {
if (deleteAccount) briarController.deleteAccount();
exit(removeFromRecentApps);
}
}

View File

@@ -16,5 +16,8 @@ public interface BriarController extends ActivityLifecycleController {
void doNotAskAgainForDozeWhiteListing();
void signOut(ResultHandler<Void> eventHandler);
void signOut(ResultHandler<Void> eventHandler, boolean deleteAccount);
void deleteAccount();
}

View File

@@ -120,7 +120,8 @@ public class BriarControllerImpl implements BriarController {
}
@Override
public void signOut(ResultHandler<Void> eventHandler) {
public void signOut(ResultHandler<Void> eventHandler,
boolean deleteAccount) {
new Thread(() -> {
try {
// Wait for the service to finish starting up
@@ -134,11 +135,18 @@ public class BriarControllerImpl implements BriarController {
service.waitForShutdown();
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for service");
} finally {
if (deleteAccount) accountManager.deleteAccount();
}
eventHandler.onResult(null);
}).start();
}
@Override
public void deleteAccount() {
accountManager.deleteAccount();
}
private void unbindService() {
if (bound) activity.unbindService(serviceConnection);
}

View File

@@ -109,7 +109,7 @@ public class NavDrawerActivity extends BriarActivity implements
} else if (intent.getBooleanExtra(INTENT_BLOGS, false)) {
startFragment(FeedFragment.newInstance(), R.id.nav_btn_blogs);
} else if (intent.getBooleanExtra(INTENT_SIGN_OUT, false)) {
signOut(false);
signOut(false, false);
}
setIntent(null);
}
@@ -279,7 +279,7 @@ public class NavDrawerActivity extends BriarActivity implements
private void signOut() {
drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED);
signOut(false);
signOut(false, false);
finish();
}

View File

@@ -5,13 +5,16 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.preference.PreferenceManager;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import info.guardianproject.GuardianProjectRSA4096;
@@ -23,18 +26,20 @@ import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class PanicResponderActivity extends BriarActivity {
private static final Logger LOG =
Logger.getLogger(PanicResponderActivity.class.getName());
@Inject
protected AccountManager accountManager;
protected LifecycleManager lifecycleManager;
@Inject
protected AndroidExecutor androidExecutor;
@Override
public void onCreate(Bundle savedInstanceState) {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TrustedIntents trustedIntents = TrustedIntents.get(this);
@@ -64,7 +69,7 @@ public class PanicResponderActivity extends BriarActivity {
// non-destructive actions are allowed by non-connected trusted apps
if (sharedPref.getBoolean(KEY_LOCK, true)) {
LOG.info("Signing out...");
signOut(true);
signOut(true, false);
}
}
}
@@ -83,14 +88,8 @@ public class PanicResponderActivity extends BriarActivity {
private void deleteAllData() {
androidExecutor.runOnBackgroundThread(() -> {
accountManager.deleteAccount();
// TODO somehow delete/shred the database more thoroughly
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
// nothing left to do after everything is deleted,
// so still sign out
LOG.info("Signing out...");
signOut(true);
signOut(true, true);
});
}
}