diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt b/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt index ee5c9f94f..1eee927a2 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessor.kt @@ -106,7 +106,7 @@ class FennecWebAppIntentProcessor( if (path.isNullOrEmpty()) return null val file = File(path) - if (!file.isUnderFennecManifestDirectory()) return null + if (!isUnderFennecManifestDirectory(file)) return null return try { // Gecko in Fennec added some add some additional data, such as cached_icon, in @@ -127,12 +127,13 @@ class FennecWebAppIntentProcessor( /** * Fennec manifests should be located in /mozilla//manifests/ */ - private fun File.isUnderFennecManifestDirectory(): Boolean { - val manifestsDir = canonicalFile.parentFile + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal fun isUnderFennecManifestDirectory(file: File): Boolean { + val manifestsDir = file.canonicalFile.parentFile // Check that manifest is in a folder named "manifests" - return manifestsDir == null || manifestsDir.name != "manifests" || + return manifestsDir != null && manifestsDir.name == "manifests" && // Check that the folder two levels up is named "mozilla" - manifestsDir.parentFile?.parentFile != getMozillaDirectory() + manifestsDir.parentFile?.parentFile?.canonicalPath == getMozillaDirectory().canonicalPath } private fun createFallbackCustomTabConfig(): CustomTabConfig { diff --git a/app/src/test/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessorTest.kt b/app/src/test/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessorTest.kt new file mode 100644 index 000000000..6e9f7c715 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/customtabs/FennecWebAppIntentProcessorTest.kt @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.customtabs + +import io.mockk.mockk +import mozilla.components.browser.session.SessionManager +import mozilla.components.feature.pwa.ManifestStorage +import mozilla.components.feature.session.SessionUseCases +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import java.io.File + +@RunWith(FenixRobolectricTestRunner::class) +class FennecWebAppIntentProcessorTest { + @Test + fun `fennec manifest path - tmp`() { + val processor = createFennecWebAppIntentProcessor() + + val file = File("/data/local/tmp/dummy_manifest.json") + assertFalse(processor.isUnderFennecManifestDirectory(file)) + } + + @Test + fun `fennec manifest path - correct path`() { + val processor = createFennecWebAppIntentProcessor() + + val file = File(testContext.filesDir.absolutePath + "/mozilla/rkgl5eyc.default/manifests/c311ad28-f331-482f-ba8f-a0fbf2c56a0d.json") + assertTrue(processor.isUnderFennecManifestDirectory(file)) + } + + @Test + fun `fennec manifest path - correct path, but other app`() { + val processor = createFennecWebAppIntentProcessor() + + val file = File("/data/data/org.other.app/files/mozilla/rkgl5eyc.default/manifests/c311ad28-f331-482f-ba8f-a0fbf2c56a0d.json") + assertFalse(processor.isUnderFennecManifestDirectory(file)) + } + + @Test + fun `fennec manifest path - root file`() { + val processor = createFennecWebAppIntentProcessor() + + val file = File("/c311ad28-f331-482f-ba8f-a0fbf2c56a0d.json") + assertFalse(processor.isUnderFennecManifestDirectory(file)) + } + + @Test + fun `fennec manifest path - tmp path rebuild`() { + val processor = createFennecWebAppIntentProcessor() + + val file = File("/data/local/tmp/files/mozilla/rkgl5eyc.default/manifests/c311ad28-f331-482f-ba8f-a0fbf2c56a0d.json") + assertFalse(processor.isUnderFennecManifestDirectory(file)) + } +} + +private fun createFennecWebAppIntentProcessor(): FennecWebAppIntentProcessor { + val sessionManager = SessionManager(engine = mockk(relaxed = true)) + val useCase: SessionUseCases.DefaultLoadUrlUseCase = mockk(relaxed = true) + val storage: ManifestStorage = mockk(relaxed = true) + + return FennecWebAppIntentProcessor( + testContext, + sessionManager, + useCase, + storage + ) +}