From de1d310499ecffdcd3e8f7a33c11385e6b7d77f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 28 May 2016 21:23:48 +0300 Subject: [PATCH] Move installation of extension into own Installer --- app/src/main/AndroidManifest.xml | 2 +- .../fdroid/installer/DefaultInstaller.java | 32 +++++-- .../fdroid/installer/ExtensionInstaller.java | 94 +++++++++++++++++++ .../fdroid/installer/InstallerFactory.java | 9 +- .../fdroid/installer/InstallerService.java | 8 +- 5 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/org/fdroid/fdroid/installer/ExtensionInstaller.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c5734f480..6f5d2d622 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -402,7 +402,7 @@ diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java index dac7c5bc3..d31d2641b 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2016 Dominik Schürmann + * + * 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; @@ -49,9 +68,9 @@ public class DefaultInstaller extends Installer { installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL); installIntent.setData(sanitizedUri); } else { - installIntent = new Intent(mContext, AndroidInstallerActivity.class); - installIntent.setAction(AndroidInstallerActivity.ACTION_INSTALL_PACKAGE); - installIntent.putExtra(AndroidInstallerActivity.EXTRA_ORIGINATING_URI, originatingUri); + installIntent = new Intent(mContext, DefaultInstallerActivity.class); + installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE); + installIntent.putExtra(DefaultInstallerActivity.EXTRA_ORIGINATING_URI, originatingUri); installIntent.setData(sanitizedUri); } @@ -63,7 +82,6 @@ public class DefaultInstaller extends Installer { sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent); - } @Override @@ -76,10 +94,10 @@ public class DefaultInstaller extends Installer { uninstallIntent = new Intent(mContext, InstallExtensionDialogActivity.class); uninstallIntent.setAction(InstallExtensionDialogActivity.ACTION_UNINSTALL); } else { - uninstallIntent = new Intent(mContext, AndroidInstallerActivity.class); - uninstallIntent.setAction(AndroidInstallerActivity.ACTION_UNINSTALL_PACKAGE); + uninstallIntent = new Intent(mContext, DefaultInstallerActivity.class); + uninstallIntent.setAction(DefaultInstallerActivity.ACTION_UNINSTALL_PACKAGE); uninstallIntent.putExtra( - AndroidInstallerActivity.EXTRA_UNINSTALL_PACKAGE_NAME, packageName); + DefaultInstallerActivity.EXTRA_UNINSTALL_PACKAGE_NAME, packageName); } PendingIntent uninstallPendingIntent = PendingIntent.getActivity( mContext.getApplicationContext(), diff --git a/app/src/main/java/org/fdroid/fdroid/installer/ExtensionInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/ExtensionInstaller.java new file mode 100644 index 000000000..887d18290 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/installer/ExtensionInstaller.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 Dominik Schürmann + * + * 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.util.Log; + +import org.fdroid.fdroid.BuildConfig; +import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity; + +import java.io.File; + +/** + * Special Installer that is only useful to install the Privileged Extension apk + */ +public class ExtensionInstaller extends Installer { + + private static final String TAG = "ExtensionInstaller"; + + ExtensionInstaller(Context context) { + super(context); + } + + @Override + protected void installPackage(Uri uri, Uri originatingUri, String packageName) { + sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_STARTED); + + Uri sanitizedUri; + try { + sanitizedUri = Installer.prepareApkFile(mContext, uri, packageName); + } catch (InstallFailedException e) { + Log.e(TAG, "prepareApkFile failed", e); + return; + } + + // extension must be signed with the same public key as main F-Droid + // NOTE: Disabled for debug builds to be able to use official extension from repo + ApkSignatureVerifier signatureVerifier = new ApkSignatureVerifier(mContext); + if (!BuildConfig.DEBUG && !signatureVerifier.hasFDroidSignature(new File(sanitizedUri.getPath()))) { + throw new RuntimeException("APK signature of extension not correct!"); + } + Intent installIntent; + installIntent = new Intent(mContext, InstallExtensionDialogActivity.class); + installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL); + installIntent.setData(sanitizedUri); + + PendingIntent installPendingIntent = PendingIntent.getActivity( + mContext.getApplicationContext(), + uri.hashCode(), + installIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + sendBroadcastInstall(uri, originatingUri, + Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent); + } + + @Override + protected void uninstallPackage(String packageName) { + sendBroadcastUninstall(packageName, Installer.ACTION_UNINSTALL_STARTED); + + Intent uninstallIntent; + uninstallIntent = new Intent(mContext, InstallExtensionDialogActivity.class); + uninstallIntent.setAction(InstallExtensionDialogActivity.ACTION_UNINSTALL); + + PendingIntent uninstallPendingIntent = PendingIntent.getActivity( + mContext.getApplicationContext(), + packageName.hashCode(), + uninstallIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + sendBroadcastUninstall(packageName, + Installer.ACTION_UNINSTALL_USER_INTERACTION, uninstallPendingIntent); + } +} diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java index 1d6f6fc6e..3f57b26e4 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerFactory.java @@ -30,9 +30,16 @@ public class InstallerFactory { private static final String TAG = "InstallerFactory"; public static Installer create(Context context) { + return create(context, null); + } + + public static Installer create(Context context, String packageName) { Installer installer; - if (isPrivilegedInstallerEnabled()) { + if (packageName != null && packageName.equals(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME)) { + // special case: F-Droid Privileged Extension + installer = new ExtensionInstaller(context); + } else if (isPrivilegedInstallerEnabled()) { if (PrivilegedInstaller.isExtensionInstalledCorrectly(context) == PrivilegedInstaller.IS_EXTENSION_INSTALLED_YES) { Utils.debugLog(TAG, "privileged extension correctly installed -> PrivilegedInstaller"); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java index 323356284..5e8fa5652 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java @@ -71,7 +71,6 @@ public class InstallerService extends Service { serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); localBroadcastManager = LocalBroadcastManager.getInstance(this); - installer = InstallerFactory.create(this); } @Override @@ -118,20 +117,19 @@ public class InstallerService extends Service { } protected void handleIntent(Intent intent) { + String packageName = intent.getStringExtra(Installer.EXTRA_PACKAGE_NAME); + installer = InstallerFactory.create(this, packageName); + switch (intent.getAction()) { case ACTION_INSTALL: { Uri uri = intent.getData(); Uri originatingUri = intent.getParcelableExtra(Installer.EXTRA_ORIGINATING_URI); - String packageName = intent.getStringExtra(Installer.EXTRA_PACKAGE_NAME); installer.installPackage(uri, originatingUri, packageName); break; } case ACTION_UNINSTALL: { - String packageName = - intent.getStringExtra(Installer.EXTRA_PACKAGE_NAME); - installer.uninstallPackage(packageName); break; }