diff --git a/app/src/full/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java b/app/src/full/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java index 330630dd7..a0b111821 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java +++ b/app/src/full/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java @@ -43,6 +43,7 @@ public class PanicPreferencesFragment extends PreferenceFragment private ListPreference prefApp; private CheckBoxPreference prefExit; private CheckBoxPreference prefHide; + private CheckBoxPreference prefResetRepos; private PreferenceCategory categoryAppsToUninstall; @Override @@ -54,6 +55,7 @@ public class PanicPreferencesFragment extends PreferenceFragment prefApp = (ListPreference) findPreference(PREF_APP); prefHide = (CheckBoxPreference) findPreference(Preferences.PREF_PANIC_HIDE); prefHide.setTitle(getString(R.string.panic_hide_title, getString(R.string.app_name))); + prefResetRepos = (CheckBoxPreference) findPreference(Preferences.PREF_PANIC_RESET_REPOS); categoryAppsToUninstall = (PreferenceCategory) findPreference("pref_panic_apps_to_uninstall"); if (PanicResponder.checkForDisconnectIntent(getActivity())) { @@ -77,9 +79,12 @@ public class PanicPreferencesFragment extends PreferenceFragment if (packageName.equals(Panic.PACKAGE_NAME_NONE)) { prefHide.setChecked(false); prefHide.setEnabled(false); + prefResetRepos.setChecked(false); + prefResetRepos.setEnabled(false); getActivity().setResult(Activity.RESULT_CANCELED); } else { prefHide.setEnabled(true); + prefResetRepos.setEnabled(true); } showPanicApp(packageName); return true; @@ -212,6 +217,7 @@ public class PanicPreferencesFragment extends PreferenceFragment prefApp.setSummary(pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0))); prefApp.setIcon(pm.getApplicationIcon(packageName)); prefHide.setEnabled(true); + prefResetRepos.setEnabled(true); showWipeList(); } catch (PackageManager.NameNotFoundException e) { // revert back to no app, just to be safe @@ -293,6 +299,7 @@ public class PanicPreferencesFragment extends PreferenceFragment @Override public void onCancel(DialogInterface dialogInterface) { prefHide.setChecked(false); + prefResetRepos.setChecked(false); } }); builder.setView(R.layout.dialog_app_hiding); diff --git a/app/src/full/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java b/app/src/full/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java index df139905c..6f3c9d9c6 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java @@ -2,6 +2,7 @@ package org.fdroid.fdroid.views.panic; import android.app.Activity; import android.content.BroadcastReceiver; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.os.Build; @@ -13,8 +14,12 @@ 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.DBHelper; import org.fdroid.fdroid.data.InstalledApp; import org.fdroid.fdroid.data.InstalledAppProvider; +import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoProvider; +import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.installer.Installer; import org.fdroid.fdroid.installer.InstallerService; import org.fdroid.fdroid.installer.PrivilegedInstaller; @@ -22,6 +27,8 @@ import org.fdroid.fdroid.views.hiding.HidingManager; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -102,6 +109,9 @@ public class PanicResponderActivity extends AppCompatActivity { // ignored } lbm.unregisterReceiver(receiver); + if (preferences.panicResetRepos()) { + resetRepos(context); + } if (preferences.panicHide()) { HidingManager.hide(context); } @@ -111,6 +121,9 @@ public class PanicResponderActivity extends AppCompatActivity { } }.start(); } else if (receivedTriggerFromConnectedApp) { + if (preferences.panicResetRepos()) { + resetRepos(this); + } // Performing destructive panic response if (preferences.panicHide()) { Log.i(TAG, "Hiding app..."); @@ -125,6 +138,33 @@ public class PanicResponderActivity extends AppCompatActivity { finish(); } + static void resetRepos(Context context) { + HashSet enabledAddresses = new HashSet<>(); + HashSet disabledAddresses = new HashSet<>(); + String[] defaultReposItems = DBHelper.loadInitialRepos(context).toArray(new String[0]); + for (int i = 1; i < defaultReposItems.length; i += DBHelper.REPO_XML_ITEM_COUNT) { + if ("1".equals(defaultReposItems[i + 3])) { + enabledAddresses.add(defaultReposItems[i]); + } else { + disabledAddresses.add(defaultReposItems[i]); + } + } + + List repos = RepoProvider.Helper.all(context); + for (Repo repo : repos) { + ContentValues values = new ContentValues(1); + if (enabledAddresses.contains(repo.address)) { + values.put(Schema.RepoTable.Cols.IN_USE, true); + RepoProvider.Helper.update(context, repo, values); + } else if (disabledAddresses.contains(repo.address)) { + values.put(Schema.RepoTable.Cols.IN_USE, false); + RepoProvider.Helper.update(context, repo, values); + } else { + RepoProvider.Helper.remove(context, repo.getId()); + } + } + } + private void exitAndClear() { ExitActivity.exitAndRemoveFromRecentApps(this); if (Build.VERSION.SDK_INT >= 21) { diff --git a/app/src/full/res/xml/preferences_panic.xml b/app/src/full/res/xml/preferences_panic.xml index 79f9925fc..b1ec1c1e6 100644 --- a/app/src/full/res/xml/preferences_panic.xml +++ b/app/src/full/res/xml/preferences_panic.xml @@ -26,6 +26,13 @@ android:summary="@string/panic_hide_summary" android:title="@string/panic_hide_title"/> + + App will hide itself Remember how to restore In a panic event, this will remove %1$s from the launcher. Only typing \"%2$d\" in the fake %3$s app can restore it. + Reset repos + Force the repo setup back to defaults Calculator diff --git a/app/src/test/java/org/fdroid/fdroid/data/FDroidProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/FDroidProviderTest.java index 416f564c5..54c3b5f9e 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/FDroidProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/FDroidProviderTest.java @@ -1,5 +1,6 @@ package org.fdroid.fdroid.data; +import android.content.ContentValues; import android.content.ContextWrapper; import org.fdroid.fdroid.TestUtils; import org.junit.After; @@ -26,4 +27,10 @@ public abstract class FDroidProviderTest { DBHelper.clearDbHelperSingleton(); } + protected Repo setEnabled(Repo repo, boolean enabled) { + ContentValues enable = new ContentValues(1); + enable.put(Schema.RepoTable.Cols.IN_USE, enabled); + RepoProvider.Helper.update(context, repo, enable); + return RepoProvider.Helper.findByAddress(context, repo.address); + } } diff --git a/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java index de6326e4f..a77624248 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/RepoProviderTest.java @@ -77,13 +77,6 @@ public class RepoProviderTest extends FDroidProviderTest { assertEquals(0, RepoProvider.Helper.countEnabledRepos(context)); } - private Repo setEnabled(Repo repo, boolean enabled) { - ContentValues enable = new ContentValues(1); - enable.put(RepoTable.Cols.IN_USE, enabled); - RepoProvider.Helper.update(context, repo, enable); - return RepoProvider.Helper.findByAddress(context, repo.address); - } - @Test public void lastUpdated() { assertNull(RepoProvider.Helper.lastUpdate(context)); diff --git a/app/src/test/java/org/fdroid/fdroid/updater/Issue763MultiRepo.java b/app/src/test/java/org/fdroid/fdroid/updater/Issue763MultiRepo.java index 606c5b6e6..5eb61fa7b 100644 --- a/app/src/test/java/org/fdroid/fdroid/updater/Issue763MultiRepo.java +++ b/app/src/test/java/org/fdroid/fdroid/updater/Issue763MultiRepo.java @@ -35,12 +35,6 @@ public class Issue763MultiRepo extends MultiIndexUpdaterTest { antoxRepo = createRepo("Tox", "https://pkg.tox.chat/fdroid/repo", context, antoxCert); } - public void setEnabled(Repo repo, boolean enabled) { - ContentValues values = new ContentValues(1); - values.put(Schema.RepoTable.Cols.IN_USE, enabled ? 1 : 0); - RepoProvider.Helper.update(context, repo, values); - } - @Test public void antoxRepo() throws IndexUpdater.UpdateException { assertAntoxEmpty(); diff --git a/app/src/testFull/java/org/fdroid/fdroid/views/panic/PanicResponderActivityTest.java b/app/src/testFull/java/org/fdroid/fdroid/views/panic/PanicResponderActivityTest.java new file mode 100644 index 000000000..6c4fdca82 --- /dev/null +++ b/app/src/testFull/java/org/fdroid/fdroid/views/panic/PanicResponderActivityTest.java @@ -0,0 +1,53 @@ +package org.fdroid.fdroid.views.panic; + +import org.fdroid.fdroid.data.DBHelper; +import org.fdroid.fdroid.data.FDroidProviderTest; +import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoProvider; +import org.fdroid.fdroid.data.RepoProviderTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(RobolectricTestRunner.class) +public class PanicResponderActivityTest extends FDroidProviderTest { + + /** + * The {@link DBHelper} class populates the default repos when it first creates a database. + * The names/URLs/signing certificates for these repos are all hard coded in the source/res. + */ + @Test + public void defaultRepos() { + List defaultRepos = RepoProvider.Helper.all(context); + assertEquals(defaultRepos.size(), 4); // based on app/src/main/res/default_repo.xml + + Repo gpRepo = RepoProvider.Helper.findByAddress(context, "https://guardianproject.info/fdroid/repo"); + setEnabled(gpRepo, true); + assertEquals(2, RepoProvider.Helper.countEnabledRepos(context)); + + PanicResponderActivity.resetRepos(context); + assertEquals(1, RepoProvider.Helper.countEnabledRepos(context)); + defaultRepos = RepoProvider.Helper.all(context); + assertEquals(4, defaultRepos.size()); + + RepoProviderTest.insertRepo( + context, + "https://mock-repo-1.example.com/fdroid/repo", + "Just a made up repo", + "ABCDEF1234567890", + "Mock Repo 1" + ); + defaultRepos = RepoProvider.Helper.all(context); + assertEquals(5, defaultRepos.size()); + assertEquals(2, RepoProvider.Helper.countEnabledRepos(context)); + + PanicResponderActivity.resetRepos(context); + defaultRepos = RepoProvider.Helper.all(context); + assertEquals(4, defaultRepos.size()); + assertEquals(1, RepoProvider.Helper.countEnabledRepos(context)); + } +}