purge deprecated, broken ExtensionInstaller, only works < android-20

This code is unmaintained, semi-broken, and only works on old Android
versions.  Time to go!

closes #982
This commit is contained in:
Hans-Christoph Steiner 2018-07-20 14:18:57 +02:00
parent b75fc8e011
commit ab767ce621
11 changed files with 0 additions and 779 deletions

View File

@ -181,11 +181,6 @@
android:key="privilegedInstaller" android:key="privilegedInstaller"
android:persistent="false" android:persistent="false"
android:dependency="expert"/> android:dependency="expert"/>
<Preference
android:title="@string/uninstall_system"
android:summary="@string/uninstall_system_summary"
android:key="uninstallPrivilegedApp"
android:dependency="expert"/>
</android.support.v7.preference.PreferenceCategory> </android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen> </android.support.v7.preference.PreferenceScreen>

View File

@ -43,11 +43,6 @@
<uses-permission android:name="android.permission.NFC"/> <uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Indicate that F-Droid may request root access (introduced by Koush's Superuser app)
This permission is deprecated, but necessary for some old superuser
apps to actually grant superuser access to F-Droid. -->
<uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>
<application> <application>
<activity <activity

View File

@ -191,17 +191,8 @@
android:finishOnTaskLaunch="true"/> android:finishOnTaskLaunch="true"/>
<activity android:name=".views.ScreenShotsActivity"/> <activity android:name=".views.ScreenShotsActivity"/>
<!-- Note: AppThemeTransparent, this activity shows dialogs only --> <!-- Note: AppThemeTransparent, this activity shows dialogs only -->
<activity
android:name=".privileged.install.InstallExtensionDialogActivity"
android:theme="@style/AppThemeTransparent"/>
<activity android:name=".data.ObbUrlActivity" <activity android:name=".data.ObbUrlActivity"
android:theme="@android:style/Theme.NoDisplay"/> android:theme="@android:style/Theme.NoDisplay"/>
<receiver
android:name=".privileged.install.InstallExtensionBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<!-- Note: AppThemeTransparent, this activity shows dialogs only --> <!-- Note: AppThemeTransparent, this activity shows dialogs only -->
<activity <activity
android:name=".installer.DefaultInstallerActivity" android:name=".installer.DefaultInstallerActivity"

View File

@ -91,7 +91,6 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
public static final String PREF_EXPERT = "expert"; public static final String PREF_EXPERT = "expert";
public static final String PREF_FORCE_OLD_INDEX = "forceOldIndex"; public static final String PREF_FORCE_OLD_INDEX = "forceOldIndex";
public static final String PREF_PRIVILEGED_INSTALLER = "privilegedInstaller"; public static final String PREF_PRIVILEGED_INSTALLER = "privilegedInstaller";
public static final String PREF_UNINSTALL_PRIVILEGED_APP = "uninstallPrivilegedApp";
public static final String PREF_LOCAL_REPO_NAME = "localRepoName"; public static final String PREF_LOCAL_REPO_NAME = "localRepoName";
public static final String PREF_LOCAL_REPO_HTTPS = "localRepoHttps"; public static final String PREF_LOCAL_REPO_HTTPS = "localRepoHttps";
public static final String PREF_LANGUAGE = "language"; public static final String PREF_LANGUAGE = "language";

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2016 Blue Jay Wireless
* Copyright (C) 2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.fdroid.fdroid.installer;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import org.fdroid.fdroid.BuildConfig;
import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity;
import java.io.File;
/**
* Special Installer that is only useful to install the Privileged Extension apk
* as a privileged app into the system partition of Android. It is deprecated
* because it cannot work on Android versions newer than {@code android-20} or so,
* due to increased SELinux enforcement that restricts what even root can do.
* <p/>
* This is installer requires user interaction and thus install/uninstall directly
* return PendingIntents.
*
* @see <a href="https://www.androidauthority.com/chainfire-rooting-android-lollipop-541458/">Chainfire talks Android Lollipop and the future of rooting</a>
*/
@Deprecated
public class ExtensionInstaller extends Installer {
ExtensionInstaller(Context context, @NonNull Apk apk) {
super(context, apk);
}
@Override
protected void installPackageInternal(Uri localApkUri, Uri downloadUri) {
// extension must be signed with the same public key as main F-Droid
// NOTE: Disabled for debug builds to be able to test official extension from repo
ApkSignatureVerifier signatureVerifier = new ApkSignatureVerifier(context);
if (!BuildConfig.DEBUG &&
!signatureVerifier.hasFDroidSignature(new File(localApkUri.getPath()))) {
sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED,
"APK signature of extension not correct!");
}
Intent installIntent = new Intent(context, InstallExtensionDialogActivity.class);
installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL);
installIntent.setData(localApkUri);
PendingIntent installPendingIntent = PendingIntent.getActivity(
context.getApplicationContext(),
localApkUri.hashCode(),
installIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
sendBroadcastInstall(downloadUri,
Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent);
// don't use broadcasts for the rest of this special installer
sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_COMPLETE);
}
@Override
protected void uninstallPackage() {
Intent uninstallIntent = new Intent(context, InstallExtensionDialogActivity.class);
uninstallIntent.setAction(InstallExtensionDialogActivity.ACTION_UNINSTALL);
PendingIntent uninstallPendingIntent = PendingIntent.getActivity(
context.getApplicationContext(),
apk.packageName.hashCode(),
uninstallIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
sendBroadcastUninstall(Installer.ACTION_UNINSTALL_USER_INTERACTION, uninstallPendingIntent);
// don't use broadcasts for the rest of this special installer
sendBroadcastUninstall(Installer.ACTION_UNINSTALL_COMPLETE);
}
@Override
protected boolean isUnattended() {
return false;
}
}

View File

@ -51,9 +51,6 @@ public class InstallerFactory {
} else if (PrivilegedInstaller.isDefault(context)) { } else if (PrivilegedInstaller.isDefault(context)) {
Utils.debugLog(TAG, "privileged extension correctly installed -> PrivilegedInstaller"); Utils.debugLog(TAG, "privileged extension correctly installed -> PrivilegedInstaller");
installer = new PrivilegedInstaller(context, apk); installer = new PrivilegedInstaller(context, apk);
} else if (apk.packageName.equals(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME)) {
// special case for installing "Privileged Extension" with root
installer = new ExtensionInstaller(context, apk);
} else { } else {
installer = new DefaultInstaller(context, apk); installer = new DefaultInstaller(context, apk);
} }

View File

@ -1,248 +0,0 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.fdroid.fdroid.privileged.install;
import android.content.Context;
import android.os.Build;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.installer.PrivilegedInstaller;
import java.util.ArrayList;
import java.util.List;
import eu.chainfire.libsuperuser.Shell;
/**
* Partly based on
* http://omerjerk.in/2014/08/how-to-install-an-app-to-system-partition/
* https://github.com/omerjerk/RemoteDroid/blob/master/app/src/main/java/in/omerjerk/remotedroid/app/MainActivity.java
*/
@SuppressWarnings("LineLength")
abstract class InstallExtension {
final Context context;
private static final String BASE_NAME = "FDroidPrivilegedExtension";
private static final String APK_FILE_NAME = BASE_NAME + ".apk";
InstallExtension(final Context context) {
this.context = context;
}
public static InstallExtension create(final Context context) {
if (Build.VERSION.SDK_INT >= 21) {
return new LollipopImpl(context);
}
if (Build.VERSION.SDK_INT >= 19) {
return new KitKatToLollipopImpl(context);
}
return new PreKitKatImpl(context);
}
final void runInstall(String apkPath) {
onPreInstall();
Shell.SU.run(getInstallCommands(apkPath));
}
final void runUninstall() {
Shell.SU.run(getUninstallCommands());
}
protected abstract String getSystemFolder();
void onPreInstall() {
// To be overridden by relevant base class[es]
}
public String getWarningString() {
return context.getString(R.string.system_install_warning);
}
public String getInstallingString() {
return context.getString(R.string.installing);
}
String getInstallPath() {
return getSystemFolder() + APK_FILE_NAME;
}
private List<String> getInstallCommands(String apkPath) {
final List<String> commands = new ArrayList<>();
commands.add("mount -o rw,remount " + FDroidApp.SYSTEM_DIR_NAME); // remount as read-write
commands.addAll(getCopyToSystemCommands(apkPath));
commands.add("mv " + getInstallPath() + ".tmp " + getInstallPath());
commands.add("sleep 5"); // wait until the app is really installed
commands.add("mount -o ro,remount " + FDroidApp.SYSTEM_DIR_NAME); // remount as read-only
commands.add("am force-stop " + PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME);
commands.addAll(getPostInstallCommands());
return commands;
}
List<String> getCopyToSystemCommands(String apkPath) {
final List<String> commands = new ArrayList<>(2);
commands.add("cat " + apkPath + " > " + getInstallPath() + ".tmp");
commands.add("chmod 644 " + getInstallPath() + ".tmp");
return commands;
}
List<String> getPostInstallCommands() {
final List<String> commands = new ArrayList<>(1);
commands.add("am start -n org.fdroid.fdroid/.privileged.install.InstallExtensionDialogActivity --ez "
+ InstallExtensionDialogActivity.ACTION_POST_INSTALL + " true");
return commands;
}
private List<String> getUninstallCommands() {
final List<String> commands = new ArrayList<>();
commands.add("am force-stop " + PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME);
commands.add("pm clear " + PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME);
commands.add("mount -o rw,remount " + FDroidApp.SYSTEM_DIR_NAME);
commands.addAll(getCleanUninstallCommands());
commands.add("sleep 5");
commands.add("mount -o ro,remount " + FDroidApp.SYSTEM_DIR_NAME);
commands.addAll(getPostUninstallCommands());
return commands;
}
List<String> getCleanUninstallCommands() {
final List<String> commands = new ArrayList<>(1);
commands.add("rm -f " + getInstallPath());
return commands;
}
List<String> getPostUninstallCommands() {
return new ArrayList<>(0);
}
private static class PreKitKatImpl extends InstallExtension {
PreKitKatImpl(Context context) {
super(context);
}
@Override
protected String getSystemFolder() {
return FDroidApp.SYSTEM_DIR_NAME + "/app/";
}
}
private static class KitKatToLollipopImpl extends InstallExtension {
KitKatToLollipopImpl(Context context) {
super(context);
}
/**
* On KitKat, "Some system apps are more system than others"
* https://github.com/android/platform_frameworks_base/commit/ccbf84f44c9e6a5ed3c08673614826bb237afc54
*/
@Override
protected String getSystemFolder() {
return FDroidApp.SYSTEM_DIR_NAME + "/priv-app/";
}
}
/**
* History of PackageManagerService in Lollipop:
* https://github.com/android/platform_frameworks_base/commits/lollipop-release/services/core/java/com/android/server/pm/PackageManagerService.java
*/
private static class LollipopImpl extends InstallExtension {
LollipopImpl(Context context) {
super(context);
}
@Override
protected void onPreInstall() {
// Setup preference to execute postInstall after reboot
Preferences.get().setPostPrivilegedInstall(true);
}
public String getWarningString() {
return context.getString(R.string.system_install_warning_lollipop);
}
public String getInstallingString() {
return context.getString(R.string.system_install_installing_rebooting);
}
/**
* Cluster-style layout where each app is placed in a unique directory
*/
@Override
protected String getSystemFolder() {
return FDroidApp.SYSTEM_DIR_NAME + "/priv-app/" + BASE_NAME + "/";
}
/**
* Create app directory
*/
@Override
protected List<String> getCopyToSystemCommands(String apkPath) {
List<String> commands = new ArrayList<>(4);
commands.add("mkdir -p " + getSystemFolder()); // create app directory if not existing
commands.add("chmod 755 " + getSystemFolder());
commands.add("cat " + apkPath + " > " + getInstallPath() + ".tmp");
commands.add("chmod 644 " + getInstallPath() + ".tmp");
return commands;
}
/**
* NOTE: Only works with reboot
*
* File observers on /system/priv-app/ have been removed because they don't work with the new
* cluser-style layout. See
* https://github.com/android/platform_frameworks_base/commit/84e71d1d61c53cd947becc7879e05947be681103
*
* Related stack overflow post: http://stackoverflow.com/q/26487750
*/
@Override
protected List<String> getPostInstallCommands() {
List<String> commands = new ArrayList<>(3);
commands.add("am broadcast -a android.intent.action.ACTION_SHUTDOWN");
commands.add("sleep 1");
commands.add("reboot");
return commands;
}
@Override
protected List<String> getCleanUninstallCommands() {
final List<String> commands = new ArrayList<>(1);
commands.add("rm -rf " + getSystemFolder());
return commands;
}
@Override
protected List<String> getPostUninstallCommands() {
List<String> commands = new ArrayList<>(3);
commands.add("am broadcast -a android.intent.action.ACTION_SHUTDOWN");
commands.add("sleep 1");
commands.add("reboot");
return commands;
}
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.fdroid.fdroid.privileged.install;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.fdroid.fdroid.Preferences;
public class InstallExtensionBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) && Preferences.get().isPostPrivilegedInstall()) {
Preferences.get().setPostPrivilegedInstall(false);
Intent postInstall = new Intent(context.getApplicationContext(), InstallExtensionDialogActivity.class);
postInstall.setAction(InstallExtensionDialogActivity.ACTION_POST_INSTALL);
postInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(postInstall);
}
}
}

View File

@ -1,336 +0,0 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.fdroid.fdroid.privileged.install;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.text.Html;
import android.util.Log;
import android.view.ContextThemeWrapper;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.installer.PrivilegedInstaller;
import org.fdroid.fdroid.views.main.MainActivity;
import java.io.File;
import eu.chainfire.libsuperuser.Shell;
/**
* Note: This activity has no view on its own, it displays consecutive dialogs.
*/
public class InstallExtensionDialogActivity extends FragmentActivity {
private static final String TAG = "InstallIntoSystem";
public static final String ACTION_INSTALL = "install";
public static final String ACTION_UNINSTALL = "uninstall";
public static final String ACTION_POST_INSTALL = "post_install";
private String apkPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// this activity itself has no content view (see manifest)
if (getIntent().getAction() == null) {
Log.e(TAG, "Please define an action!");
finish();
return;
}
Uri dataUri = getIntent().getData();
if (dataUri != null) {
File apkFile = new File(dataUri.getPath());
apkPath = apkFile.getAbsolutePath();
}
switch (getIntent().getAction()) {
case ACTION_UNINSTALL:
uninstall();
break;
case ACTION_INSTALL:
askBeforeInstall();
break;
case ACTION_POST_INSTALL:
postInstall();
break;
}
}
private void askBeforeInstall() {
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
// not support on Android >= 5.1
if (android.os.Build.VERSION.SDK_INT >= 22) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(theme);
alertBuilder.setMessage(R.string.system_install_not_supported);
alertBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
InstallExtensionDialogActivity.this.setResult(Activity.RESULT_CANCELED);
InstallExtensionDialogActivity.this.finish();
}
});
alertBuilder.create().show();
return;
}
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(theme);
alertBuilder.setTitle(R.string.system_install_question);
String message = InstallExtension.create(getApplicationContext()).getWarningString();
alertBuilder.setMessage(Html.fromHtml(message));
alertBuilder.setPositiveButton(R.string.system_install_button_install, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
checkRootTask.execute();
}
});
alertBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
InstallExtensionDialogActivity.this.setResult(Activity.RESULT_CANCELED);
InstallExtensionDialogActivity.this.finish();
}
});
alertBuilder.create().show();
}
/**
* 1. Check for root access
*/
private final AsyncTask<Void, Void, Boolean> checkRootTask = new AsyncTask<Void, Void, Boolean>() {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(InstallExtensionDialogActivity.this,
FDroidApp.getCurThemeResId());
progressDialog = new ProgressDialog(theme);
progressDialog.setMessage(getString(R.string.requesting_root_access_body));
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.show();
}
@Override
protected Boolean doInBackground(Void... params) {
return Shell.SU.available();
}
@Override
protected void onPostExecute(Boolean rootGranted) {
super.onPostExecute(rootGranted);
progressDialog.dismiss();
if (rootGranted) {
// root access granted
switch (getIntent().getAction()) {
case ACTION_UNINSTALL:
uninstallTask.execute();
break;
case ACTION_INSTALL:
installTask.execute();
break;
}
} else {
// root access denied
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(InstallExtensionDialogActivity.this,
FDroidApp.getCurThemeResId());
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(theme)
.setTitle(R.string.root_access_denied_title)
.setMessage(getString(R.string.root_access_denied_body))
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
InstallExtensionDialogActivity.this.setResult(Activity.RESULT_CANCELED);
InstallExtensionDialogActivity.this.finish();
}
});
alertBuilder.create().show();
}
}
};
/**
* 2. Install into system
*/
private final AsyncTask<Void, Void, Void> installTask = new AsyncTask<Void, Void, Void>() {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(InstallExtensionDialogActivity.this,
FDroidApp.getCurThemeResId());
progressDialog = new ProgressDialog(theme);
progressDialog.setMessage(InstallExtension.create(getApplicationContext()).getInstallingString());
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.show();
}
@Override
protected Void doInBackground(Void... voids) {
InstallExtension.create(getApplicationContext()).runInstall(apkPath);
return null;
}
};
/**
* 3. Verify that install worked
*/
private void postInstall() {
int isInstalledCorrectly =
PrivilegedInstaller.isExtensionInstalledCorrectly(this);
String title;
String message;
final int result;
switch (isInstalledCorrectly) {
case PrivilegedInstaller.IS_EXTENSION_INSTALLED_YES:
title = getString(R.string.system_install_post_success);
message = getString(R.string.system_install_post_success_message);
result = Activity.RESULT_OK;
break;
case PrivilegedInstaller.IS_EXTENSION_INSTALLED_NO:
title = getString(R.string.system_install_post_fail);
message = getString(R.string.system_install_post_fail_message);
result = Activity.RESULT_CANCELED;
break;
case PrivilegedInstaller.IS_EXTENSION_INSTALLED_SIGNATURE_PROBLEM:
title = getString(R.string.system_install_post_fail);
message = getString(R.string.system_install_post_fail_message) +
"\n\n" + getString(R.string.system_install_denied_signature);
result = Activity.RESULT_CANCELED;
break;
default:
throw new RuntimeException("unhandled return");
}
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
AlertDialog.Builder builder = new AlertDialog.Builder(theme)
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
InstallExtensionDialogActivity.this.setResult(result);
InstallExtensionDialogActivity.this.finish();
startActivity(new Intent(InstallExtensionDialogActivity.this, MainActivity.class));
}
})
.setCancelable(false);
builder.create().show();
}
private void uninstall() {
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
final boolean isInstalled = PrivilegedInstaller.isExtensionInstalled(this);
if (isInstalled) {
String message = InstallExtension.create(getApplicationContext()).getWarningString();
AlertDialog.Builder builder = new AlertDialog.Builder(theme)
.setTitle(R.string.system_uninstall)
.setMessage(Html.fromHtml(message))
.setPositiveButton(R.string.system_uninstall_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
checkRootTask.execute();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
InstallExtensionDialogActivity.this.setResult(Activity.RESULT_CANCELED);
InstallExtensionDialogActivity.this.finish();
}
});
builder.create().show();
} else {
throw new RuntimeException("Uninstall invoked, but extension is not installed!");
}
}
private final AsyncTask<Void, Void, Void> uninstallTask = new AsyncTask<Void, Void, Void>() {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(InstallExtensionDialogActivity.this,
FDroidApp.getCurThemeResId());
progressDialog = new ProgressDialog(theme);
progressDialog.setMessage(getString(R.string.uninstalling));
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.show();
}
@Override
protected Void doInBackground(Void... voids) {
InstallExtension.create(getApplicationContext()).runUninstall();
return null;
}
@Override
protected void onPostExecute(Void unused) {
super.onPostExecute(unused);
progressDialog.dismiss();
// app is uninstalled but still display, kill it!
System.exit(0);
}
};
}

View File

@ -44,7 +44,6 @@ import android.text.TextUtils;
import android.view.WindowManager; import android.view.WindowManager;
import info.guardianproject.netcipher.NetCipher; import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.proxy.OrbotHelper; import info.guardianproject.netcipher.proxy.OrbotHelper;
import org.fdroid.fdroid.AppDetails2;
import org.fdroid.fdroid.CleanCacheService; import org.fdroid.fdroid.CleanCacheService;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Languages; import org.fdroid.fdroid.Languages;
@ -100,7 +99,6 @@ public class PreferencesFragment extends PreferenceFragment
private SwitchPreference enableProxyCheckPref; private SwitchPreference enableProxyCheckPref;
private SwitchPreference useTorCheckPref; private SwitchPreference useTorCheckPref;
private Preference updateAutoDownloadPref; private Preference updateAutoDownloadPref;
private Preference updatePrivilegedExtensionPref;
private CheckBoxPreference keepInstallHistoryPref; private CheckBoxPreference keepInstallHistoryPref;
private Preference installHistoryPref; private Preference installHistoryPref;
private long currentKeepCacheTime; private long currentKeepCacheTime;
@ -123,7 +121,6 @@ public class PreferencesFragment extends PreferenceFragment
useTorCheckPref = (SwitchPreference) findPreference(Preferences.PREF_USE_TOR); useTorCheckPref = (SwitchPreference) findPreference(Preferences.PREF_USE_TOR);
enableProxyCheckPref = (SwitchPreference) findPreference(Preferences.PREF_ENABLE_PROXY); enableProxyCheckPref = (SwitchPreference) findPreference(Preferences.PREF_ENABLE_PROXY);
updateAutoDownloadPref = findPreference(Preferences.PREF_AUTO_DOWNLOAD_INSTALL_UPDATES); updateAutoDownloadPref = findPreference(Preferences.PREF_AUTO_DOWNLOAD_INSTALL_UPDATES);
updatePrivilegedExtensionPref = findPreference(Preferences.PREF_UNINSTALL_PRIVILEGED_APP);
overWifiSeekBar = (LiveSeekBarPreference) findPreference(Preferences.PREF_OVER_WIFI); overWifiSeekBar = (LiveSeekBarPreference) findPreference(Preferences.PREF_OVER_WIFI);
overWifiPrevious = overWifiSeekBar.getValue(); overWifiPrevious = overWifiSeekBar.getValue();
@ -402,28 +399,6 @@ public class PreferencesFragment extends PreferenceFragment
} }
} }
private void initUpdatePrivilegedExtensionPreference() {
if (Build.VERSION.SDK_INT > 19) {
// this will never work on newer Android versions, so hide it
otherPrefGroup.removePreference(updatePrivilegedExtensionPref);
return;
}
updatePrivilegedExtensionPref.setPersistent(false);
updatePrivilegedExtensionPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
// Open details of F-Droid Privileged
Intent intent = new Intent(getActivity(), AppDetails2.class);
intent.putExtra(AppDetails2.EXTRA_APPID,
PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME);
startActivity(intent);
return true;
}
});
}
/** /**
* If a user specifies they want to fetch updates automatically, then start the download of relevant * If a user specifies they want to fetch updates automatically, then start the download of relevant
* updates as soon as they enable the feature. * updates as soon as they enable the feature.
@ -490,7 +465,6 @@ public class PreferencesFragment extends PreferenceFragment
initAutoFetchUpdatesPreference(); initAutoFetchUpdatesPreference();
initPrivilegedInstallerPreference(); initPrivilegedInstallerPreference();
initUpdatePrivilegedExtensionPreference();
initUseTorPreference(); initUseTorPreference();
} }

View File

@ -207,11 +207,6 @@
android:key="privilegedInstaller" android:key="privilegedInstaller"
android:persistent="false" android:persistent="false"
android:dependency="expert"/> android:dependency="expert"/>
<Preference
android:title="@string/uninstall_system"
android:summary="@string/uninstall_system_summary"
android:key="uninstallPrivilegedApp"
android:dependency="expert"/>
</android.support.v7.preference.PreferenceCategory> </android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen> </android.support.v7.preference.PreferenceScreen>