mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-20 06:47:06 -04:00
[app] pass App object into installers, so it is available everywhere where needed
This commit is contained in:
committed by
Hans-Christoph Steiner
parent
d3b5620035
commit
b0748fc11f
@@ -3,12 +3,12 @@ package org.fdroid.fdroid.panic;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.DBHelper;
|
||||
import org.fdroid.fdroid.installer.Installer;
|
||||
import org.fdroid.fdroid.installer.InstallerService;
|
||||
@@ -87,9 +87,11 @@ public class PanicResponderActivity extends AppCompatActivity {
|
||||
lbm.registerReceiver(receiver, Installer.getUninstallIntentFilter(lastToUninstall));
|
||||
|
||||
for (String packageName : wipeList) {
|
||||
App app = new App();
|
||||
Apk apk = new Apk();
|
||||
app.packageName = packageName;
|
||||
apk.packageName = packageName;
|
||||
InstallerService.uninstall(context, apk);
|
||||
InstallerService.uninstall(context, app, apk);
|
||||
}
|
||||
|
||||
// wait for apps to uninstall before triggering final responses
|
||||
|
||||
@@ -443,6 +443,17 @@ public final class AppUpdateStatusManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public App getApp(String canonicalUrl) {
|
||||
synchronized (appMapping) {
|
||||
AppUpdateStatus entry = appMapping.get(canonicalUrl);
|
||||
if (entry != null) {
|
||||
return entry.app;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Apk getApk(String canonicalUrl) {
|
||||
synchronized (appMapping) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -41,8 +42,8 @@ public class DefaultInstaller extends Installer {
|
||||
|
||||
public static final String TAG = "DefaultInstaller";
|
||||
|
||||
DefaultInstaller(Context context, @NonNull Apk apk) {
|
||||
super(context, apk);
|
||||
DefaultInstaller(Context context, @NonNull App app, @NonNull Apk apk) {
|
||||
super(context, app, apk);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,6 +52,7 @@ public class DefaultInstaller extends Installer {
|
||||
Intent installIntent = new Intent(context, DefaultInstallerActivity.class);
|
||||
installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE);
|
||||
installIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
|
||||
installIntent.putExtra(Installer.EXTRA_APP, app);
|
||||
installIntent.putExtra(Installer.EXTRA_APK, apk);
|
||||
installIntent.setData(localApkUri);
|
||||
|
||||
@@ -68,6 +70,7 @@ public class DefaultInstaller extends Installer {
|
||||
protected void uninstallPackage() {
|
||||
Intent uninstallIntent = new Intent(context, DefaultInstallerActivity.class);
|
||||
uninstallIntent.setAction(DefaultInstallerActivity.ACTION_UNINSTALL_PACKAGE);
|
||||
uninstallIntent.putExtra(Installer.EXTRA_APP, app);
|
||||
uninstallIntent.putExtra(Installer.EXTRA_APK, apk);
|
||||
PendingIntent uninstallPendingIntent = PendingIntent.getActivity(
|
||||
context.getApplicationContext(),
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@@ -65,8 +66,9 @@ public class DefaultInstallerActivity extends FragmentActivity {
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
App app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
installer = new DefaultInstaller(this, apk);
|
||||
installer = new DefaultInstaller(this, app, apk);
|
||||
if (ACTION_INSTALL_PACKAGE.equals(action)) {
|
||||
Uri localApkUri = intent.getData();
|
||||
canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
|
||||
|
||||
@@ -25,14 +25,15 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class FileInstaller extends Installer {
|
||||
|
||||
public FileInstaller(Context context, @NonNull Apk apk) {
|
||||
super(context, apk);
|
||||
public FileInstaller(Context context, @NonNull App app, @NonNull Apk apk) {
|
||||
super(context, app, apk);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +56,7 @@ public class FileInstaller extends Installer {
|
||||
Intent installIntent = new Intent(context, FileInstallerActivity.class);
|
||||
installIntent.setAction(FileInstallerActivity.ACTION_INSTALL_FILE);
|
||||
installIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
|
||||
installIntent.putExtra(Installer.EXTRA_APP, app);
|
||||
installIntent.putExtra(Installer.EXTRA_APK, apk);
|
||||
installIntent.setData(localApkUri);
|
||||
|
||||
@@ -72,6 +74,7 @@ public class FileInstaller extends Installer {
|
||||
protected void uninstallPackage() {
|
||||
Intent uninstallIntent = new Intent(context, FileInstallerActivity.class);
|
||||
uninstallIntent.setAction(FileInstallerActivity.ACTION_UNINSTALL_FILE);
|
||||
uninstallIntent.putExtra(Installer.EXTRA_APP, app);
|
||||
uninstallIntent.putExtra(Installer.EXTRA_APK, apk);
|
||||
PendingIntent uninstallPendingIntent = PendingIntent.getActivity(
|
||||
context.getApplicationContext(),
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import java.io.File;
|
||||
@@ -40,6 +41,7 @@ public class FileInstallerActivity extends FragmentActivity {
|
||||
// for the broadcasts
|
||||
private FileInstaller installer;
|
||||
|
||||
private App app;
|
||||
private Apk apk;
|
||||
private Uri localApkUri;
|
||||
/**
|
||||
@@ -56,8 +58,9 @@ public class FileInstallerActivity extends FragmentActivity {
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
localApkUri = intent.getData();
|
||||
app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
installer = new FileInstaller(this, apk);
|
||||
installer = new FileInstaller(this, app, apk);
|
||||
if (ACTION_INSTALL_FILE.equals(action)) {
|
||||
canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
|
||||
if (hasStoragePermission()) {
|
||||
@@ -182,7 +185,7 @@ public class FileInstallerActivity extends FragmentActivity {
|
||||
*/
|
||||
private boolean postInstall(Uri canonicalUri, Apk apk, File path) {
|
||||
if (path.getName().endsWith(".obf") || path.getName().endsWith(".obf.zip")) {
|
||||
ObfInstallerService.install(this, canonicalUri, apk, path);
|
||||
ObfInstallerService.install(this, canonicalUri, app, apk, path);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -354,9 +354,10 @@ public class InstallManagerService extends Service {
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
registerInstallReceiver(canonicalUrl);
|
||||
|
||||
App app = appUpdateStatusManager.getApp(canonicalUrl);
|
||||
Apk apk = appUpdateStatusManager.getApk(canonicalUrl);
|
||||
if (apk != null) {
|
||||
InstallerService.install(context, localApkUri, canonicalUri, apk);
|
||||
InstallerService.install(context, localApkUri, canonicalUri, app, apk);
|
||||
}
|
||||
break;
|
||||
case DownloaderService.ACTION_INTERRUPTED:
|
||||
@@ -389,6 +390,7 @@ public class InstallManagerService extends Service {
|
||||
return;
|
||||
}
|
||||
String canonicalUrl = intent.getDataString();
|
||||
App app;
|
||||
Apk apk;
|
||||
switch (intent.getAction()) {
|
||||
case Installer.ACTION_INSTALL_STARTED:
|
||||
@@ -410,20 +412,22 @@ public class InstallManagerService extends Service {
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
break;
|
||||
case Installer.ACTION_INSTALL_INTERRUPTED:
|
||||
app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
String errorMessage =
|
||||
intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
appUpdateStatusManager.setApkError(null, apk, errorMessage);
|
||||
appUpdateStatusManager.setApkError(app, apk, errorMessage);
|
||||
} else {
|
||||
appUpdateStatusManager.removeApk(canonicalUrl);
|
||||
}
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
break;
|
||||
case Installer.ACTION_INSTALL_USER_INTERACTION:
|
||||
app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
PendingIntent installPendingIntent = intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
|
||||
appUpdateStatusManager.addApk(null, apk, AppUpdateStatusManager.Status.ReadyToInstall, installPendingIntent);
|
||||
appUpdateStatusManager.addApk(app, apk, AppUpdateStatusManager.Status.ReadyToInstall, installPendingIntent);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("intent action not handled!");
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.util.Log;
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.privileged.views.AppDiff;
|
||||
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
||||
import org.fdroid.fdroid.privileged.views.InstallConfirmActivity;
|
||||
@@ -52,6 +53,7 @@ public abstract class Installer {
|
||||
private static final String TAG = "Installer";
|
||||
|
||||
final Context context;
|
||||
final App app;
|
||||
final Apk apk;
|
||||
|
||||
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".installer";
|
||||
@@ -66,6 +68,7 @@ public abstract class Installer {
|
||||
public static final String ACTION_UNINSTALL_INTERRUPTED = "org.fdroid.fdroid.installer.Installer.action.UNINSTALL_INTERRUPTED";
|
||||
public static final String ACTION_UNINSTALL_USER_INTERACTION = "org.fdroid.fdroid.installer.Installer.action.UNINSTALL_USER_INTERACTION";
|
||||
|
||||
public static final String EXTRA_APP = "org.fdroid.fdroid.installer.Installer.extra.APP";
|
||||
public static final String EXTRA_APK = "org.fdroid.fdroid.installer.Installer.extra.APK";
|
||||
public static final String EXTRA_USER_INTERACTION_PI = "org.fdroid.fdroid.installer.Installer.extra.USER_INTERACTION_PI";
|
||||
public static final String EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.installer.Installer.extra.ERROR_MESSAGE";
|
||||
@@ -74,8 +77,9 @@ public abstract class Installer {
|
||||
* @param apk must be included so that all the phases of the install process
|
||||
* can get all the data about the app, even after F-Droid was killed
|
||||
*/
|
||||
Installer(Context context, @NonNull Apk apk) {
|
||||
Installer(Context context, @NonNull App app, @NonNull Apk apk) {
|
||||
this.context = context;
|
||||
this.app = app;
|
||||
this.apk = apk;
|
||||
}
|
||||
|
||||
@@ -97,6 +101,7 @@ public abstract class Installer {
|
||||
return null;
|
||||
}
|
||||
Intent intent = new Intent(context, InstallConfirmActivity.class);
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
|
||||
return intent;
|
||||
@@ -147,34 +152,37 @@ public abstract class Installer {
|
||||
Utils.debugLog(TAG, "Falling back to default installer for uninstall");
|
||||
Intent intent = new Intent(context, DefaultInstallerActivity.class);
|
||||
intent.setAction(DefaultInstallerActivity.ACTION_UNINSTALL_PACKAGE);
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
return intent;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, UninstallDialogActivity.class);
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
void sendBroadcastInstall(Uri canonicalUri, String action, PendingIntent pendingIntent) {
|
||||
sendBroadcastInstall(context, canonicalUri, action, apk, pendingIntent, null);
|
||||
sendBroadcastInstall(context, canonicalUri, action, app, apk, pendingIntent, null);
|
||||
}
|
||||
|
||||
void sendBroadcastInstall(Uri canonicalUri, String action) {
|
||||
sendBroadcastInstall(context, canonicalUri, action, apk, null, null);
|
||||
sendBroadcastInstall(context, canonicalUri, action, app, apk, null, null);
|
||||
}
|
||||
|
||||
void sendBroadcastInstall(Uri canonicalUri, String action, String errorMessage) {
|
||||
sendBroadcastInstall(context, canonicalUri, action, apk, null, errorMessage);
|
||||
sendBroadcastInstall(context, canonicalUri, action, app, apk, null, errorMessage);
|
||||
}
|
||||
|
||||
static void sendBroadcastInstall(Context context,
|
||||
Uri canonicalUri, String action, Apk apk,
|
||||
Uri canonicalUri, String action, App app, Apk apk,
|
||||
PendingIntent pendingIntent, String errorMessage) {
|
||||
Intent intent = new Intent(action);
|
||||
intent.setData(canonicalUri);
|
||||
intent.putExtra(Installer.EXTRA_USER_INTERACTION_PI, pendingIntent);
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
intent.putExtra(Installer.EXTRA_ERROR_MESSAGE, errorMessage);
|
||||
@@ -195,19 +203,20 @@ public abstract class Installer {
|
||||
}
|
||||
|
||||
private void sendBroadcastUninstall(String action, PendingIntent pendingIntent, String errorMessage) {
|
||||
sendBroadcastUninstall(context, apk, action, pendingIntent, errorMessage);
|
||||
sendBroadcastUninstall(context, app, apk, action, pendingIntent, errorMessage);
|
||||
}
|
||||
|
||||
static void sendBroadcastUninstall(Context context, Apk apk, String action) {
|
||||
sendBroadcastUninstall(context, apk, action, null, null);
|
||||
static void sendBroadcastUninstall(Context context, App app, Apk apk, String action) {
|
||||
sendBroadcastUninstall(context, app, apk, action, null, null);
|
||||
}
|
||||
|
||||
private static void sendBroadcastUninstall(Context context, Apk apk, String action,
|
||||
private static void sendBroadcastUninstall(Context context, App app, Apk apk, String action,
|
||||
PendingIntent pendingIntent, String errorMessage) {
|
||||
Uri uri = Uri.fromParts("package", apk.packageName, null);
|
||||
|
||||
Intent intent = new Intent(action);
|
||||
intent.setData(uri); // for broadcast filtering
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
intent.putExtra(Installer.EXTRA_USER_INTERACTION_PI, pendingIntent);
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
@@ -300,7 +309,7 @@ public abstract class Installer {
|
||||
if (isUnattended()) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
Log.e(TAG, "Falling back to AOSP DefaultInstaller!");
|
||||
DefaultInstaller defaultInstaller = new DefaultInstaller(context, apk);
|
||||
DefaultInstaller defaultInstaller = new DefaultInstaller(context, app, apk);
|
||||
defaultInstaller.installPackageInternal(sanitizedUri, canonicalUri);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -38,10 +39,11 @@ public class InstallerFactory {
|
||||
* case to install the "F-Droid Privileged Extension" ExtensionInstaller.
|
||||
*
|
||||
* @param context current {@link Context}
|
||||
* @param app to be installed, always required.
|
||||
* @param apk to be installed, always required.
|
||||
* @return instance of an Installer
|
||||
*/
|
||||
public static Installer create(Context context, @NonNull Apk apk) {
|
||||
public static Installer create(Context context, @NonNull App app, @NonNull Apk apk) {
|
||||
if (TextUtils.isEmpty(apk.packageName)) {
|
||||
throw new IllegalArgumentException("Apk.packageName must not be empty: " + apk);
|
||||
}
|
||||
@@ -49,12 +51,12 @@ public class InstallerFactory {
|
||||
Installer installer;
|
||||
if (!apk.isApk()) {
|
||||
Utils.debugLog(TAG, "Using FileInstaller for non-apk file");
|
||||
installer = new FileInstaller(context, apk);
|
||||
installer = new FileInstaller(context, app, apk);
|
||||
} else if (PrivilegedInstaller.isDefault(context)) {
|
||||
Utils.debugLog(TAG, "privileged extension correctly installed -> PrivilegedInstaller");
|
||||
installer = new PrivilegedInstaller(context, apk);
|
||||
installer = new PrivilegedInstaller(context, app, apk);
|
||||
} else {
|
||||
installer = new DefaultInstaller(context, apk);
|
||||
installer = new DefaultInstaller(context, app, apk);
|
||||
}
|
||||
|
||||
return installer;
|
||||
|
||||
@@ -68,11 +68,12 @@ public class InstallerService extends JobIntentService {
|
||||
|
||||
@Override
|
||||
protected void onHandleWork(@NonNull Intent intent) {
|
||||
final App app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
if (apk == null) {
|
||||
return;
|
||||
}
|
||||
Installer installer = InstallerFactory.create(this, apk);
|
||||
Installer installer = InstallerFactory.create(this, app, apk);
|
||||
|
||||
if (ACTION_INSTALL.equals(intent.getAction())) {
|
||||
Uri uri = intent.getData();
|
||||
@@ -120,13 +121,14 @@ public class InstallerService extends JobIntentService {
|
||||
* @see #uninstall(Context, Apk)
|
||||
* @see InstallManagerService
|
||||
*/
|
||||
public static void install(Context context, Uri localApkUri, Uri canonicalUri, Apk apk) {
|
||||
Installer.sendBroadcastInstall(context, canonicalUri, Installer.ACTION_INSTALL_STARTED, apk,
|
||||
null, null);
|
||||
public static void install(Context context, Uri localApkUri, Uri canonicalUri, App app, Apk apk) {
|
||||
Installer.sendBroadcastInstall(context, canonicalUri, Installer.ACTION_INSTALL_STARTED, app,
|
||||
apk, null, null);
|
||||
Intent intent = new Intent(context, InstallerService.class);
|
||||
intent.setAction(ACTION_INSTALL);
|
||||
intent.setData(localApkUri);
|
||||
intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
enqueueWork(context, intent);
|
||||
}
|
||||
@@ -148,13 +150,14 @@ public class InstallerService extends JobIntentService {
|
||||
* @param context this app's {@link Context}
|
||||
* @param apk {@link Apk} instance of the app that will be uninstalled
|
||||
*/
|
||||
public static void uninstall(Context context, @NonNull Apk apk) {
|
||||
public static void uninstall(Context context, @NonNull App app, @NonNull Apk apk) {
|
||||
Objects.requireNonNull(apk);
|
||||
|
||||
Installer.sendBroadcastUninstall(context, apk, Installer.ACTION_UNINSTALL_STARTED);
|
||||
Installer.sendBroadcastUninstall(context, app, apk, Installer.ACTION_UNINSTALL_STARTED);
|
||||
|
||||
Intent intent = new Intent(context, InstallerService.class);
|
||||
intent.setAction(ACTION_UNINSTALL);
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
enqueueWork(context, intent);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.webkit.MimeTypeMap;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.DownloaderService;
|
||||
|
||||
import java.io.File;
|
||||
@@ -38,10 +39,11 @@ public class ObfInstallerService extends IntentService {
|
||||
super("ObfInstallerService");
|
||||
}
|
||||
|
||||
public static void install(Context context, Uri canonicalUri, Apk apk, File path) {
|
||||
public static void install(Context context, Uri canonicalUri, App app, Apk apk, File path) {
|
||||
Intent intent = new Intent(context, ObfInstallerService.class);
|
||||
intent.setAction(ACTION_INSTALL_OBF);
|
||||
intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
|
||||
intent.putExtra(Installer.EXTRA_APP, app);
|
||||
intent.putExtra(Installer.EXTRA_APK, apk);
|
||||
intent.putExtra(EXTRA_OBF_PATH, path.getAbsolutePath());
|
||||
context.startService(intent);
|
||||
@@ -54,15 +56,16 @@ public class ObfInstallerService extends IntentService {
|
||||
return;
|
||||
}
|
||||
Uri canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
|
||||
final App app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
final String path = intent.getStringExtra(EXTRA_OBF_PATH);
|
||||
final String extension = MimeTypeMap.getFileExtensionFromUrl(path);
|
||||
if ("obf".equals(extension)) {
|
||||
sendPostInstallAndCompleteIntents(canonicalUri, apk, new File(path));
|
||||
sendPostInstallAndCompleteIntents(canonicalUri, app, apk, new File(path));
|
||||
return;
|
||||
}
|
||||
if (!"zip".equals(extension)) {
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, apk,
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, app, apk,
|
||||
"Only .obf and .zip files are supported: " + path);
|
||||
return;
|
||||
}
|
||||
@@ -70,7 +73,7 @@ public class ObfInstallerService extends IntentService {
|
||||
File zip = new File(path);
|
||||
ZipFile zipFile = new ZipFile(zip);
|
||||
if (zipFile.size() < 1) {
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, apk,
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, app, apk,
|
||||
"Corrupt or empty ZIP file!");
|
||||
}
|
||||
ZipEntry zipEntry = zipFile.entries().nextElement();
|
||||
@@ -79,15 +82,15 @@ public class ObfInstallerService extends IntentService {
|
||||
FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), extracted);
|
||||
// Since we delete the file here, it won't show as installed anymore
|
||||
zip.delete();
|
||||
sendPostInstallAndCompleteIntents(canonicalUri, apk, extracted);
|
||||
sendPostInstallAndCompleteIntents(canonicalUri, app, apk, extracted);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, apk, e.getMessage());
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, app, apk, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBroadcastInstall(String action, Uri canonicalUri, Apk apk, String msg) {
|
||||
Installer.sendBroadcastInstall(this, canonicalUri, action, apk, null, msg);
|
||||
private void sendBroadcastInstall(String action, Uri canonicalUri, App app, Apk apk, String msg) {
|
||||
Installer.sendBroadcastInstall(this, canonicalUri, action, app, apk, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +100,7 @@ public class ObfInstallerService extends IntentService {
|
||||
* When this was written, OsmAnd only supported importing OBF files via a
|
||||
* {@code file:///} URL, so this disables {@link android.os.FileUriExposedException}.
|
||||
*/
|
||||
void sendPostInstallAndCompleteIntents(Uri canonicalUri, Apk apk, File file) {
|
||||
void sendPostInstallAndCompleteIntents(Uri canonicalUri, App app, Apk apk, File file) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
try {
|
||||
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
|
||||
@@ -122,10 +125,10 @@ public class ObfInstallerService extends IntentService {
|
||||
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivity(intent);
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_COMPLETE, canonicalUri, apk, null);
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_COMPLETE, canonicalUri, app, apk, null);
|
||||
} else {
|
||||
Log.i(TAG, "No AppCompatActivity available to handle " + intent);
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, apk, null);
|
||||
sendBroadcastInstall(Installer.ACTION_INSTALL_INTERRUPTED, canonicalUri, app, apk, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.privileged.IPrivilegedCallback;
|
||||
import org.fdroid.fdroid.privileged.IPrivilegedService;
|
||||
|
||||
@@ -251,8 +252,8 @@ public class PrivilegedInstaller extends Installer {
|
||||
"device owner has marked the package as uninstallable.");
|
||||
}
|
||||
|
||||
PrivilegedInstaller(Context context, @NonNull Apk apk) {
|
||||
super(context, apk);
|
||||
PrivilegedInstaller(Context context, App app, @NonNull Apk apk) {
|
||||
super(context, app, apk);
|
||||
}
|
||||
|
||||
private static boolean isExtensionInstalled(Context context) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.view.ContextThemeWrapper;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.installer.Installer;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -50,6 +51,7 @@ public class UninstallDialogActivity extends FragmentActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
final App app = intent.getParcelableExtra(Installer.EXTRA_APP);
|
||||
final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||
|
||||
PackageManager pm = getPackageManager();
|
||||
@@ -89,6 +91,7 @@ public class UninstallDialogActivity extends FragmentActivity {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent data = new Intent();
|
||||
data.putExtra(Installer.EXTRA_APP, app);
|
||||
data.putExtra(Installer.EXTRA_APK, apk);
|
||||
setResult(AppCompatActivity.RESULT_OK, intent);
|
||||
finish();
|
||||
|
||||
@@ -426,7 +426,7 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
private void initiateInstall(Apk apk) {
|
||||
Installer installer = InstallerFactory.create(this, apk);
|
||||
Installer installer = InstallerFactory.create(this, app, apk);
|
||||
Intent intent = installer.getPermissionScreen();
|
||||
if (intent != null) {
|
||||
// permission screen required
|
||||
@@ -440,7 +440,7 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
|
||||
private void startUninstall() {
|
||||
registerUninstallReceiver();
|
||||
InstallerService.uninstall(this, app.installedApk);
|
||||
InstallerService.uninstall(this, app, app.installedApk);
|
||||
}
|
||||
|
||||
private void registerUninstallReceiver() {
|
||||
@@ -837,7 +837,7 @@ public class AppDetailsActivity extends AppCompatActivity
|
||||
}
|
||||
app.installedApk = apk;
|
||||
}
|
||||
Installer installer = InstallerFactory.create(this, apk);
|
||||
Installer installer = InstallerFactory.create(this, app, apk);
|
||||
Intent intent = installer.getUninstallScreen();
|
||||
if (intent != null) {
|
||||
// uninstall screen required
|
||||
|
||||
@@ -537,7 +537,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
||||
|
||||
Uri canonicalUri = Uri.parse(canonicalUrl);
|
||||
broadcastManager.registerReceiver(receiver, Installer.getInstallIntentFilter(canonicalUri));
|
||||
Installer installer = InstallerFactory.create(activity, currentStatus.apk);
|
||||
Installer installer = InstallerFactory.create(activity, currentStatus.app, currentStatus.apk);
|
||||
installer.installPackage(Uri.parse(apkFilePath.toURI().toString()), canonicalUri);
|
||||
} else {
|
||||
FDroidDatabase db = DBHelper.getDb(activity);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class KnownVulnAppListItemController extends AppListItemController {
|
||||
InstallManagerService.queue(activity, app, currentApk);
|
||||
} else {
|
||||
manager.registerReceiver(installReceiver, Installer.getUninstallIntentFilter(app.packageName));
|
||||
InstallerService.uninstall(activity, installedApk);
|
||||
InstallerService.uninstall(activity, app, installedApk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.ContextWrapper;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.index.v2.FileV1;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -30,12 +31,14 @@ public class FileInstallerTest {
|
||||
|
||||
@Test
|
||||
public void testInstallOtaZip() {
|
||||
App app = new App();
|
||||
app.packageName = "org.fdroid.fdroid.privileged.ota";
|
||||
Apk apk = new Apk();
|
||||
apk.apkFile = new FileV1("org.fdroid.fdroid.privileged.ota_2010.zip", "hash", null, null);
|
||||
apk.packageName = "org.fdroid.fdroid.privileged.ota";
|
||||
apk.versionCode = 2010;
|
||||
assertFalse(apk.isApk());
|
||||
Installer installer = InstallerFactory.create(context, apk);
|
||||
Installer installer = InstallerFactory.create(context, app, apk);
|
||||
assertEquals("should be a FileInstaller",
|
||||
FileInstaller.class,
|
||||
installer.getClass());
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.ContextWrapper;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.index.v2.FileV1;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -28,10 +29,12 @@ public class InstallerFactoryTest {
|
||||
@Test
|
||||
public void testApkInstallerInstance() {
|
||||
for (String filename : new String[]{"test.apk", "A.APK", "b.ApK"}) {
|
||||
App app = new App();
|
||||
app.packageName = "test";
|
||||
Apk apk = new Apk();
|
||||
apk.apkFile = new FileV1(filename, "hash", null, null);
|
||||
apk.packageName = "test";
|
||||
Installer installer = InstallerFactory.create(context, apk);
|
||||
Installer installer = InstallerFactory.create(context, app, apk);
|
||||
assertEquals(filename + " should use a DefaultInstaller",
|
||||
DefaultInstaller.class,
|
||||
installer.getClass());
|
||||
@@ -41,10 +44,12 @@ public class InstallerFactoryTest {
|
||||
@Test
|
||||
public void testFileInstallerInstance() {
|
||||
for (String filename : new String[]{"org.fdroid.fdroid.privileged.ota_2110.zip", "test.ZIP"}) {
|
||||
App app = new App();
|
||||
app.packageName = "cafe0088";
|
||||
Apk apk = new Apk();
|
||||
apk.apkFile = new FileV1(filename, "hash", null, null);
|
||||
apk.packageName = "cafe0088";
|
||||
Installer installer = InstallerFactory.create(context, apk);
|
||||
Installer installer = InstallerFactory.create(context, app, apk);
|
||||
assertEquals("should be a FileInstaller",
|
||||
FileInstaller.class,
|
||||
installer.getClass());
|
||||
|
||||
Reference in New Issue
Block a user