From 5a0092d42e155d8b8f51354147fbaf6b11553773 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 19 Oct 2020 15:58:20 +0200 Subject: [PATCH] use shared method for getting full installed path for media files --- .../main/java/org/fdroid/fdroid/data/Apk.java | 6 ++- .../installer/FileInstallerActivity.java | 18 +++---- .../views/AppDetailsRecyclerViewAdapter.java | 2 +- .../fdroid/installer/FileInstallerTest.java | 47 +++++++++++++++++ .../installer/InstallerFactoryTest.java | 50 +++++++++++++++++++ 5 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java create mode 100644 app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java index 8bf1c7ad7..f0553d7ce 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java @@ -588,8 +588,12 @@ public class Apk extends ValueObject implements Comparable, Parcelable { return path; } + public File getInstalledMediaFile(Context context) { + return new File(this.getMediaInstallPath(context), SanitizedFile.sanitizeFileName(this.apkName)); + } + public boolean isMediaInstalled(Context context) { - return new File(this.getMediaInstallPath(context), SanitizedFile.sanitizeFileName(this.apkName)).isFile(); + return getInstalledMediaFile(context).isFile(); } /** diff --git a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java index 7896ac3fe..23b804d0f 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java @@ -6,13 +6,13 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.core.content.ContextCompat; -import androidx.appcompat.app.AlertDialog; import android.view.ContextThemeWrapper; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; @@ -148,10 +148,10 @@ public class FileInstallerActivity extends FragmentActivity { private void installPackage(Uri localApkUri, Uri canonicalUri, Apk apk) { Utils.debugLog(TAG, "Installing: " + localApkUri.getPath()); - File path = apk.getMediaInstallPath(activity.getApplicationContext()); - path.mkdirs(); + File path = apk.getInstalledMediaFile(activity.getApplicationContext()); + path.getParentFile().mkdirs(); try { - FileUtils.copyFileToDirectory(new File(localApkUri.getPath()), path); + FileUtils.copyFile(new File(localApkUri.getPath()), path); } catch (IOException e) { Utils.debugLog(TAG, "Failed to copy: " + e.getMessage()); installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); @@ -169,7 +169,7 @@ public class FileInstallerActivity extends FragmentActivity { private void uninstallPackage(Apk apk) { if (apk.isMediaInstalled(activity.getApplicationContext())) { - File file = new File(apk.getMediaInstallPath(activity.getApplicationContext()), apk.apkName); + File file = apk.getInstalledMediaFile(activity.getApplicationContext()); if (!file.delete()) { installer.sendBroadcastUninstall(Installer.ACTION_UNINSTALL_INTERRUPTED); return; diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java index 5673b2a79..6bfe1d2e1 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java @@ -604,7 +604,7 @@ public class AppDetailsRecyclerViewAdapter } }); } else if (!app.isApk && mediaApk != null) { - final File installedFile = new File(mediaApk.getMediaInstallPath(context), mediaApk.apkName); + final File installedFile = mediaApk.getInstalledMediaFile(context); if (!installedFile.toString().startsWith(context.getApplicationInfo().dataDir)) { final Intent viewIntent = new Intent(Intent.ACTION_VIEW); Uri uri = FileProvider.getUriForFile(context, Installer.AUTHORITY, installedFile); diff --git a/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java b/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java new file mode 100644 index 000000000..0fb3976a2 --- /dev/null +++ b/app/src/test/java/org/fdroid/fdroid/installer/FileInstallerTest.java @@ -0,0 +1,47 @@ +package org.fdroid.fdroid.installer; + +import android.content.ContextWrapper; +import androidx.test.core.app.ApplicationProvider; +import org.fdroid.fdroid.Preferences; +import org.fdroid.fdroid.TestUtils; +import org.fdroid.fdroid.data.Apk; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowLog; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +@RunWith(RobolectricTestRunner.class) +public class FileInstallerTest { + public static final String TAG = "FileInstallerTest"; + + private ContextWrapper context; + + @Before + public final void setUp() { + context = ApplicationProvider.getApplicationContext(); + Preferences.setupForTests(context); + ShadowLog.stream = System.out; + } + + @Test + public void testInstallOtaZip() { + Apk apk = new Apk(); + apk.apkName = "org.fdroid.fdroid.privileged.ota_2010.zip"; + apk.packageName = "org.fdroid.fdroid.privileged.ota"; + apk.versionCode = 2010; + assertFalse(apk.isApk()); + Installer installer = InstallerFactory.create(context, apk); + assertEquals("should be a FileInstaller", + FileInstaller.class, + installer.getClass()); + } +} diff --git a/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java b/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java new file mode 100644 index 000000000..a455fd57d --- /dev/null +++ b/app/src/test/java/org/fdroid/fdroid/installer/InstallerFactoryTest.java @@ -0,0 +1,50 @@ +package org.fdroid.fdroid.installer; + +import android.content.ContextWrapper; +import androidx.test.core.app.ApplicationProvider; +import org.fdroid.fdroid.Preferences; +import org.fdroid.fdroid.data.Apk; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(RobolectricTestRunner.class) +public class InstallerFactoryTest { + + private ContextWrapper context; + + @Before + public final void setUp() { + context = ApplicationProvider.getApplicationContext(); + Preferences.setupForTests(context); + } + + @Test + public void testApkInstallerInstance() { + for (String filename : new String[]{"test.apk", "A.APK", "b.ApK"}) { + Apk apk = new Apk(); + apk.apkName = filename; + apk.packageName = "test"; + Installer installer = InstallerFactory.create(context, apk); + assertEquals(filename + " should use a DefaultInstaller", + DefaultInstaller.class, + installer.getClass()); + } + } + + @Test + public void testFileInstallerInstance() { + for (String filename : new String[]{"org.fdroid.fdroid.privileged.ota_2110.zip", "test.ZIP"}) { + Apk apk = new Apk(); + apk.apkName = filename; + apk.packageName = "cafe0088"; + Installer installer = InstallerFactory.create(context, apk); + assertEquals("should be a FileInstaller", + FileInstaller.class, + installer.getClass()); + } + } +}