Bug 1796189 - List extensions installed outside the list of featured extensions

Co-authored-by: William Durand <will+git@drnd.me>
Co-authored-by: Arturo Mejia <arturomejiamarmol@gmail.com>
fenix/119.0
William Durand 11 months ago committed by mergify[bot]
parent d743c46919
commit 9fd7b0f27b

@ -78,10 +78,8 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management)
webExtensionPromptFeature.set(
feature = WebExtensionPromptFeature(
store = requireComponents.core.store,
provideAddons = { addons },
context = requireContext(),
fragmentManager = parentFragmentManager,
snackBarParentView = view,
onAddonChanged = {
runIfFragmentIsAttached {
adapter?.updateAddon(it)

@ -62,7 +62,6 @@ import mozilla.components.concept.engine.permission.SitePermissions
import mozilla.components.concept.engine.prompt.ShareData
import mozilla.components.feature.accounts.FxaCapability
import mozilla.components.feature.accounts.FxaWebChannelFeature
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.app.links.AppLinksFeature
import mozilla.components.feature.contextmenu.ContextMenuCandidate
import mozilla.components.feature.contextmenu.ContextMenuFeature
@ -138,7 +137,6 @@ import org.mozilla.fenix.downloads.ThirdPartyDownloadDialog
import org.mozilla.fenix.ext.accessibilityManager
import org.mozilla.fenix.ext.breadcrumb
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getFenixAddons
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.hideToolbar
import org.mozilla.fenix.ext.nav
@ -918,10 +916,8 @@ abstract class BaseBrowserFragment :
webExtensionPromptFeature.set(
feature = WebExtensionPromptFeature(
store = requireComponents.core.store,
provideAddons = ::provideAddons,
context = requireContext(),
fragmentManager = parentFragmentManager,
snackBarParentView = binding.dynamicSnackbarContainer,
),
owner = this,
view = view,
@ -1653,13 +1649,4 @@ abstract class BaseBrowserFragment :
return isValidStatus && isSameTab
}
private suspend fun provideAddons(): List<Addon> {
return withContext(IO) {
// We deactivated the cache to get the most up-to-date list of add-ons to match against.
// as this will be used to install add-ons from AMO.
val addons = requireContext().components.addonManager.getFenixAddons(allowCache = false)
addons
}
}
}

@ -6,7 +6,6 @@ package org.mozilla.fenix.extension
import android.content.Context
import android.view.Gravity
import android.view.View
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.FragmentManager
import kotlinx.coroutines.CoroutineScope
@ -23,8 +22,6 @@ import mozilla.components.feature.addons.ui.PermissionsDialogFragment
import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.support.base.feature.LifecycleAwareFeature
import org.mozilla.fenix.R
import org.mozilla.fenix.addons.showSnackBar
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.ThemeManager
import java.lang.ref.WeakReference
@ -34,9 +31,7 @@ import java.lang.ref.WeakReference
*/
class WebExtensionPromptFeature(
private val store: BrowserStore,
private val provideAddons: suspend () -> List<Addon>,
private val context: Context,
private val snackBarParentView: View,
private val fragmentManager: FragmentManager,
private val onAddonChanged: (Addon) -> Unit = {},
) : LifecycleAwareFeature {
@ -56,9 +51,11 @@ class WebExtensionPromptFeature(
flow.mapNotNull { state ->
state.webExtensionPromptRequest
}.distinctUntilChanged().collect { promptRequest ->
val addon = provideAddons().find { addon ->
addon.id == promptRequest.extension.id
}
// The install flow in Fenix relies on an [Addon] object so let's convert the (GeckoView)
// extension into a minimal add-on. The missing metadata will be fetched when the user
// opens the add-ons manager.
val addon = Addon.newFromWebExtension(promptRequest.extension)
when (promptRequest) {
is WebExtensionPromptRequest.Permissions -> handlePermissionRequest(
addon,
@ -66,7 +63,7 @@ class WebExtensionPromptFeature(
)
is WebExtensionPromptRequest.PostInstallation -> handlePostInstallationRequest(
addon?.copy(installedState = promptRequest.extension.toInstalledState()),
addon.copy(installedState = promptRequest.extension.toInstalledState()),
)
}
}
@ -75,31 +72,20 @@ class WebExtensionPromptFeature(
}
private fun handlePostInstallationRequest(
addon: Addon?,
addon: Addon,
) {
if (addon == null) {
consumePromptRequest()
return
}
showPostInstallationDialog(addon)
}
private fun handlePermissionRequest(
addon: Addon?,
addon: Addon,
promptRequest: WebExtensionPromptRequest.Permissions,
) {
if (hasExistingPermissionDialogFragment()) return
if (addon == null) {
promptRequest.onConfirm(false)
consumePromptRequest()
showUnsupportedError()
} else {
showPermissionDialog(
addon,
promptRequest,
)
if (hasExistingPermissionDialogFragment()) {
return
}
showPermissionDialog(addon, promptRequest)
}
/**
@ -145,15 +131,6 @@ class WebExtensionPromptFeature(
}
}
@VisibleForTesting
internal fun showUnsupportedError() {
showSnackBar(
snackBarParentView,
context.getString(R.string.addon_not_supported_error),
FenixSnackbar.LENGTH_LONG,
)
}
private fun tryToReAttachButtonHandlersToPreviousDialog() {
findPreviousPermissionDialogFragment()?.let { dialog ->
dialog.onPositiveButtonClicked = { addon ->

@ -1,63 +0,0 @@
/* 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.extension
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.spyk
import io.mockk.verify
import mozilla.components.browser.state.action.WebExtensionAction.UpdatePromptRequestWebExtensionAction
import mozilla.components.browser.state.state.extension.WebExtensionPromptRequest.Permissions
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@RunWith(FenixRobolectricTestRunner::class)
class WebExtensionPromptFeatureTest {
private lateinit var webExtensionPromptFeature: WebExtensionPromptFeature
private lateinit var store: BrowserStore
@get:Rule
val coroutinesTestRule = MainCoroutineRule()
@Before
fun setup() {
store = BrowserStore()
webExtensionPromptFeature = spyk(
WebExtensionPromptFeature(
store = store,
provideAddons = { emptyList() },
context = testContext,
snackBarParentView = mockk(relaxed = true),
fragmentManager = mockk(relaxed = true),
),
)
}
@Test
fun `WHEN add-on is not found THEN unsupported error message is shown`() {
val onConfirm = mockk<(Boolean) -> Unit>(relaxed = true)
every { webExtensionPromptFeature.consumePromptRequest() } just runs
every { webExtensionPromptFeature.showUnsupportedError() } returns mockk()
webExtensionPromptFeature.start()
// Passing a mocked WebExtension instance here will result in no add-on being found.
store.dispatch(UpdatePromptRequestWebExtensionAction(Permissions(mockk(), onConfirm))).joinBlocking()
verify { onConfirm(false) }
verify { webExtensionPromptFeature.consumePromptRequest() }
verify { webExtensionPromptFeature.showUnsupportedError() }
}
}
Loading…
Cancel
Save