Revert "Bug 1867717 - Add DownloadsFeature to AddonPopupBaseFragment."

This reverts commit cc65693e4f8811906f344d0e902af0bccbb7edbf.
fenix/125.0
Rahul Sainani 2 months ago committed by mergify[bot]
parent a878e4b3fa
commit 2d7942033c

@ -12,7 +12,6 @@ import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import mozilla.components.feature.addons.ui.translateName
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.DownloadDialogLayoutBinding
import org.mozilla.fenix.databinding.FragmentAddOnInternalSettingsBinding
import org.mozilla.fenix.ext.showToolbar
@ -22,8 +21,6 @@ import org.mozilla.fenix.ext.showToolbar
class AddonInternalSettingsFragment : AddonPopupBaseFragment() {
private val args by navArgs<AddonInternalSettingsFragmentArgs>()
private var _binding: FragmentAddOnInternalSettingsBinding? = null
internal val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
@ -34,17 +31,9 @@ class AddonInternalSettingsFragment : AddonPopupBaseFragment() {
return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false)
}
override fun getSnackBarContainer(): ViewGroup {
return binding.dynamicSnackbarContainer
}
override fun getDownloadDialogLayoutBinding(): DownloadDialogLayoutBinding {
return binding.viewDynamicDownloadDialog
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAddOnInternalSettingsBinding.bind(view)
val binding = FragmentAddOnInternalSettingsBinding.bind(view)
args.addon.installedState?.optionsPageUrl?.let {
engineSession?.let { engineSession ->
binding.addonSettingsEngineView.render(engineSession)
@ -59,9 +48,4 @@ class AddonInternalSettingsFragment : AddonPopupBaseFragment() {
showToolbar(title = args.addon.translateName(it))
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

@ -5,33 +5,21 @@
package org.mozilla.fenix.addons
import android.os.Bundle
import android.os.Environment
import android.view.View
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.Snackbar
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.action.CustomTabListAction
import mozilla.components.browser.state.state.CustomTabSessionState
import mozilla.components.browser.state.state.EngineState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.createCustomTab
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.concept.engine.window.WindowRequest
import mozilla.components.concept.fetch.Response
import mozilla.components.feature.downloads.DownloadsFeature
import mozilla.components.feature.prompts.PromptFeature
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.browser.DownloadDialogUtils
import org.mozilla.fenix.components.DownloadStyling
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.databinding.DownloadDialogLayoutBinding
import org.mozilla.fenix.downloads.DynamicDownloadDialog
import org.mozilla.fenix.ext.requireComponents
/**
@ -40,22 +28,19 @@ import org.mozilla.fenix.ext.requireComponents
*/
abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, UserInteractionHandler {
private val promptsFeature = ViewBoundFeatureWrapper<PromptFeature>()
private val downloadsFeature = ViewBoundFeatureWrapper<DownloadsFeature>()
internal var session: SessionState? = null
protected var session: SessionState? = null
protected var engineSession: EngineSession? = null
private var canGoBack: Boolean = false
@Suppress("DEPRECATION")
// https://github.com/mozilla-mobile/fenix/issues/19920
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val store = requireComponents.core.store
val safeContext = requireContext()
session?.let {
promptsFeature.set(
feature = PromptFeature(
fragment = this,
store = store,
store = requireComponents.core.store,
customTabId = it.id,
fragmentManager = parentFragmentManager,
fileUploadsDirCleaner = requireComponents.core.fileUploadsDirCleaner,
@ -67,52 +52,6 @@ abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, User
owner = this,
view = view,
)
downloadsFeature.set(
DownloadsFeature(
safeContext,
store = store,
useCases = requireComponents.useCases.downloadUseCases,
fragmentManager = parentFragmentManager,
tabId = it.id,
downloadManager = requireComponents.downloadManager,
promptsStyling = DownloadStyling.createPrompt(safeContext),
onNeedToRequestPermissions = { permissions ->
requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS)
},
),
owner = this,
view = view,
)
downloadsFeature.get()?.onDownloadStopped = { downloadState, _, downloadJobStatus ->
val onCannotOpenFile: (DownloadState) -> Unit = {
FenixSnackbar.make(
view = getSnackBarContainer(),
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = true,
).setText(DynamicDownloadDialog.getCannotOpenFileErrorMessage(requireContext(), it))
.show()
}
DownloadDialogUtils.handleOnDownloadFinished(
context = requireContext(),
downloadState = downloadState,
downloadJobStatus = downloadJobStatus,
currentTab = it,
onCannotOpenFile = onCannotOpenFile,
onFinishedDialogShown = {
DynamicDownloadDialog(
context = requireContext(),
downloadState = downloadState,
didFail = downloadJobStatus == DownloadState.Status.FAILED,
tryAgain = downloadsFeature.get()!!::tryAgain,
onCannotOpenFile = onCannotOpenFile,
binding = getDownloadDialogLayoutBinding(),
toolbarHeight = 0,
) {}.show()
},
)
}
}
}
@ -134,44 +73,6 @@ abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, User
engineSession?.unregister(this)
}
override fun onExternalResource(
url: String,
fileName: String?,
contentLength: Long?,
contentType: String?,
cookie: String?,
userAgent: String?,
isPrivate: Boolean,
skipConfirmation: Boolean,
openInApp: Boolean,
response: Response?,
) {
session?.let { session ->
val fileSize = if (contentLength != null && contentLength < 0) null else contentLength
val download = DownloadState(
url,
fileName,
contentType,
fileSize,
0,
DownloadState.Status.INITIATED,
userAgent,
Environment.DIRECTORY_DOWNLOADS,
private = isPrivate,
skipConfirmation = skipConfirmation,
openInApp = openInApp,
response = response,
)
provideBrowserStore().dispatch(
ContentAction.UpdateDownloadAction(
session.id,
download,
),
)
}
}
override fun onPromptRequest(promptRequest: PromptRequest) {
session?.let { session ->
requireComponents.core.store.dispatch(
@ -213,34 +114,17 @@ abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, User
requireComponents.core.store.dispatch(CustomTabListAction.AddCustomTabAction(session as CustomTabSessionState))
}
@VisibleForTesting
internal fun provideBrowserStore() = requireComponents.core.store
final override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray,
) {
val feature = when (requestCode) {
REQUEST_CODE_PROMPT_PERMISSIONS -> promptsFeature.get()
REQUEST_CODE_DOWNLOAD_PERMISSIONS -> downloadsFeature.get()
else -> null
when (requestCode) {
REQUEST_CODE_PROMPT_PERMISSIONS -> promptsFeature.get()?.onPermissionsResult(permissions, grantResults)
}
feature?.onPermissionsResult(permissions, grantResults)
}
/**
* Returns a [ViewGroup] where a SnackBar message should be anchored.
*/
abstract fun getSnackBarContainer(): ViewGroup
/**
* Returns a [DownloadDialogLayoutBinding] to access the download dialog items.
*/
abstract fun getDownloadDialogLayoutBinding(): DownloadDialogLayoutBinding
companion object {
private const val REQUEST_CODE_PROMPT_PERMISSIONS = 1
private const val REQUEST_CODE_DOWNLOAD_PERMISSIONS = 2
}
}

@ -15,7 +15,6 @@ import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineView
import mozilla.components.lib.state.ext.consumeFrom
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.DownloadDialogLayoutBinding
import org.mozilla.fenix.databinding.FragmentAddOnInternalSettingsBinding
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.showToolbar
@ -34,9 +33,6 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession.
safeArguments.putBoolean("isSessionConsumed", value)
}
private var _binding: FragmentAddOnInternalSettingsBinding? = null
internal val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -50,14 +46,6 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession.
return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false)
}
override fun getSnackBarContainer(): ViewGroup {
return binding.dynamicSnackbarContainer
}
override fun getDownloadDialogLayoutBinding(): DownloadDialogLayoutBinding {
return binding.viewDynamicDownloadDialog
}
override fun onResume() {
super.onResume()
val title = args.webExtensionTitle ?: args.webExtensionId
@ -67,7 +55,7 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAddOnInternalSettingsBinding.bind(view)
val binding = FragmentAddOnInternalSettingsBinding.bind(view)
val session = engineSession
// If we have the session, render it otherwise consume it from the store.
@ -94,11 +82,6 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession.
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun consumePopupSession() {
coreComponents.store.dispatch(
WebExtensionAction.UpdatePopupSessionAction(args.webExtensionId, popupSession = null),

@ -13,6 +13,7 @@ import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -72,6 +73,7 @@ import mozilla.components.feature.app.links.AppLinksFeature
import mozilla.components.feature.contextmenu.ContextMenuCandidate
import mozilla.components.feature.contextmenu.ContextMenuFeature
import mozilla.components.feature.downloads.DownloadsFeature
import mozilla.components.feature.downloads.manager.FetchDownloadManager
import mozilla.components.feature.downloads.temporary.CopyDownloadFeature
import mozilla.components.feature.downloads.temporary.ShareDownloadFeature
import mozilla.components.feature.intent.ext.EXTRA_SESSION_ID
@ -127,7 +129,6 @@ import org.mozilla.fenix.OnBackLongPressedListener
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
import org.mozilla.fenix.components.DownloadStyling
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.FindInPageIntegration
import org.mozilla.fenix.components.StoreProvider
@ -150,6 +151,7 @@ import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.crashes.CrashContentIntegration
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.databinding.FragmentBrowserBinding
import org.mozilla.fenix.downloads.DownloadService
import org.mozilla.fenix.downloads.DynamicDownloadDialog
import org.mozilla.fenix.downloads.FirstPartyDownloadDialog
import org.mozilla.fenix.downloads.StartDownloadDialog
@ -639,14 +641,31 @@ abstract class BaseBrowserFragment :
useCases = context.components.useCases.downloadUseCases,
fragmentManager = childFragmentManager,
tabId = customTabSessionId,
downloadManager = context.components.downloadManager,
downloadManager = FetchDownloadManager(
context.applicationContext,
store,
DownloadService::class,
notificationsDelegate = context.components.notificationsDelegate,
),
shouldForwardToThirdParties = {
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
context.getPreferenceKey(R.string.pref_key_external_download_manager),
false,
)
},
promptsStyling = DownloadStyling.createPrompt(context),
promptsStyling = DownloadsFeature.PromptsStyling(
gravity = Gravity.BOTTOM,
shouldWidthMatchParent = true,
positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
R.attr.accent,
context,
),
positiveButtonTextColor = ThemeManager.resolveAttribute(
R.attr.textOnColorPrimary,
context,
),
positiveButtonRadius = (resources.getDimensionPixelSize(R.dimen.tab_corner_radius)).toFloat(),
),
onNeedToRequestPermissions = { permissions ->
requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS)
},
@ -699,46 +718,7 @@ abstract class BaseBrowserFragment :
)
downloadFeature.onDownloadStopped = { downloadState, _, downloadJobStatus ->
val onCannotOpenFile: (DownloadState) -> Unit = {
FenixSnackbar.make(
view = binding.dynamicSnackbarContainer,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = true,
).setText(
DynamicDownloadDialog.getCannotOpenFileErrorMessage(
context,
downloadState,
),
).show()
}
DownloadDialogUtils.handleOnDownloadFinished(
context = requireContext(),
downloadState = downloadState,
downloadJobStatus = downloadJobStatus,
currentTab = getCurrentTab(),
onFinishedDialogShown = {
saveDownloadDialogState(
downloadState.sessionId,
downloadState,
downloadJobStatus,
)
browserToolbarView.expand()
DynamicDownloadDialog(
context = context,
downloadState = downloadState,
didFail = downloadJobStatus == DownloadState.Status.FAILED,
tryAgain = downloadFeature::tryAgain,
onCannotOpenFile = onCannotOpenFile,
binding = binding.viewDynamicDownloadDialog,
toolbarHeight = toolbarHeight,
) {
sharedViewModel.downloadDialogState.remove(downloadState.sessionId)
}.show()
},
onCannotOpenFile = onCannotOpenFile,
)
handleOnDownloadFinished(downloadState, downloadJobStatus, downloadFeature::tryAgain)
}
resumeDownloadDialogState(
@ -1244,12 +1224,7 @@ abstract class BaseBrowserFragment :
didFail = savedDownloadState.second,
tryAgain = onTryAgain,
onCannotOpenFile = {
FenixSnackbar.make(
view = binding.dynamicSnackbarContainer,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = true,
).setText(DynamicDownloadDialog.getCannotOpenFileErrorMessage(context, it))
.show()
showCannotOpenFileError(binding.dynamicSnackbarContainer, context, it)
},
binding = binding.viewDynamicDownloadDialog,
toolbarHeight = toolbarHeight,
@ -1757,6 +1732,19 @@ abstract class BaseBrowserFragment :
)
}
internal fun showCannotOpenFileError(
container: ViewGroup,
context: Context,
downloadState: DownloadState,
) {
FenixSnackbar.make(
view = container,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = true,
).setText(DynamicDownloadDialog.getCannotOpenFileErrorMessage(context, downloadState))
.show()
}
companion object {
private const val KEY_CUSTOM_TAB_SESSION_ID = "custom_tab_session_id"
private const val REQUEST_CODE_DOWNLOAD_PERMISSIONS = 1

@ -1,62 +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.browser
import android.content.Context
import androidx.annotation.VisibleForTesting
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.content.DownloadState.Status
import mozilla.components.feature.downloads.AbstractFetchDownloadService
/**
* Utilities for handling download dialogs.
*/
object DownloadDialogUtils {
internal fun handleOnDownloadFinished(
context: Context,
downloadState: DownloadState,
downloadJobStatus: Status,
currentTab: SessionState?,
onFinishedDialogShown: () -> Unit = {},
onCannotOpenFile: (DownloadState) -> Unit,
) {
// If the download is just paused, don't show any in-app notification
if (shouldShowCompletedDownloadDialog(downloadState, downloadJobStatus, currentTab)) {
if (downloadState.openInApp && downloadJobStatus == Status.COMPLETED) {
val fileWasOpened = openFile(context, downloadState)
if (!fileWasOpened) {
onCannotOpenFile(downloadState)
}
} else {
onFinishedDialogShown()
}
}
}
@VisibleForTesting
internal var openFile: (Context, DownloadState) -> (Boolean) = { context, downloadState ->
AbstractFetchDownloadService.openFile(
applicationContext = context.applicationContext,
download = downloadState,
)
}
/**
* Indicates whether or not a completed download dialog should be shown.
*/
fun shouldShowCompletedDownloadDialog(
downloadState: DownloadState,
status: Status,
currentTab: SessionState?,
): Boolean {
val isValidStatus =
status in listOf(Status.COMPLETED, Status.FAILED)
val isSameTab = downloadState.sessionId == (currentTab?.id ?: false)
return isValidStatus && isSameTab
}
}

@ -0,0 +1,53 @@
/* 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.browser
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.content.DownloadState.Status
import mozilla.components.feature.downloads.AbstractFetchDownloadService
import org.mozilla.fenix.R
import org.mozilla.fenix.downloads.DynamicDownloadDialog
internal fun BaseBrowserFragment.handleOnDownloadFinished(
downloadState: DownloadState,
downloadJobStatus: Status,
tryAgain: (String) -> Unit,
) {
// If the download is just paused, don't show any in-app notification
if (shouldShowCompletedDownloadDialog(downloadState, downloadJobStatus)) {
val safeContext = context ?: return
val onCannotOpenFile: (DownloadState) -> Unit = {
showCannotOpenFileError(binding.dynamicSnackbarContainer, safeContext, it)
}
if (downloadState.openInApp && downloadJobStatus == Status.COMPLETED) {
val fileWasOpened = AbstractFetchDownloadService.openFile(
applicationContext = safeContext.applicationContext,
download = downloadState,
)
if (!fileWasOpened) {
onCannotOpenFile(downloadState)
}
} else {
saveDownloadDialogState(
downloadState.sessionId,
downloadState,
downloadJobStatus,
)
val dynamicDownloadDialog = DynamicDownloadDialog(
context = safeContext,
downloadState = downloadState,
didFail = downloadJobStatus == Status.FAILED,
tryAgain = tryAgain,
onCannotOpenFile = onCannotOpenFile,
binding = binding.viewDynamicDownloadDialog,
toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height),
) { sharedViewModel.downloadDialogState.remove(downloadState.sessionId) }
dynamicDownloadDialog.show()
browserToolbarView.expand()
}
}
}

@ -16,7 +16,6 @@ import mozilla.components.feature.addons.amo.AMOAddonsProvider
import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker
import mozilla.components.feature.addons.update.DefaultAddonUpdater
import mozilla.components.feature.autofill.AutofillConfiguration
import mozilla.components.feature.downloads.manager.FetchDownloadManager
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.base.android.NotificationsDelegate
import mozilla.components.support.base.worker.Frequency
@ -30,7 +29,6 @@ import org.mozilla.fenix.autofill.AutofillUnlockActivity
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.metrics.MetricsMiddleware
import org.mozilla.fenix.datastore.pocketStoriesSelectedCategoriesDataStore
import org.mozilla.fenix.downloads.DownloadService
import org.mozilla.fenix.ext.asRecentTabs
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.filterState
@ -101,15 +99,6 @@ class Components(private val context: Context) {
)
}
val downloadManager by lazyMonitored {
FetchDownloadManager(
context.applicationContext,
core.store,
DownloadService::class,
notificationsDelegate = notificationsDelegate,
)
}
val intentProcessors by lazyMonitored {
IntentProcessors(
context,

@ -1,36 +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.components
import android.content.Context
import android.view.Gravity
import mozilla.components.feature.downloads.DownloadsFeature
import org.mozilla.fenix.R
import org.mozilla.fenix.theme.ThemeManager
/**
* Provides access to all Fenix download styling.
*/
object DownloadStyling {
/**
* creates [DownloadsFeature.PromptsStyling].
*/
fun createPrompt(context: Context): DownloadsFeature.PromptsStyling {
return DownloadsFeature.PromptsStyling(
gravity = Gravity.BOTTOM,
shouldWidthMatchParent = true,
positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
R.attr.accent,
context,
),
positiveButtonTextColor = ThemeManager.resolveAttribute(
R.attr.textOnColorPrimary,
context,
),
positiveButtonRadius = (context.resources.getDimensionPixelSize(R.dimen.tab_corner_radius)).toFloat(),
)
}
}

@ -13,18 +13,4 @@
android:id="@+id/addonSettingsEngineView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/viewDynamicDownloadDialog"
layout="@layout/download_dialog_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="gone" />
<FrameLayout
android:id="@+id/dynamicSnackbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="@dimen/browser_fragment_toolbar_elevation"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -1,53 +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.addons
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.fetch.Response
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@RunWith(FenixRobolectricTestRunner::class)
class AddonPopupBaseFragmentTest {
private lateinit var fragment: AddonPopupBaseFragment
@Before
fun setup() {
fragment = spyk()
}
@Test
fun `WHEN onExternalResource is call THEN dispatch an UpdateDownloadAction`() {
val store = mockk<BrowserStore>(relaxed = true)
val session = mockk<SessionState>(relaxed = true)
val response = mockk<Response>(relaxed = true)
every { fragment.provideBrowserStore() } returns store
fragment.session = session
fragment.onExternalResource(
url = "url",
fileName = "fileName",
contentLength = 1,
contentType = "contentType",
userAgent = "userAgent",
isPrivate = true,
skipConfirmation = false,
openInApp = false,
response = response,
)
verify { store.dispatch(any<ContentAction.UpdateDownloadAction>()) }
}
}

@ -12,7 +12,11 @@ import io.mockk.mockk
import io.mockk.slot
import io.mockk.spyk
import io.mockk.verify
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.createTab
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.engine.permission.SitePermissions
import mozilla.components.feature.contextmenu.ContextMenuCandidate
@ -104,7 +108,6 @@ class BaseBrowserFragmentTest {
}
@Test
@Suppress("ktlint:standard:max-line-length")
fun `initializeEngineView should set toolbar height as EngineView parent's bottom margin when using bottom toolbar`() {
every { settings.isDynamicToolbarEnabled } returns false
every { settings.shouldUseBottomToolbar } returns true
@ -115,7 +118,7 @@ class BaseBrowserFragmentTest {
}
@Test
fun `initializeEngineView set toolbar height as EngineView parent's bottom margin if top toolbar`() {
fun `initializeEngineView should set toolbar height as EngineView parent's bottom margin if top toolbar is forced for a11y`() {
every { settings.shouldUseBottomToolbar } returns false
every { settings.shouldUseFixedTopToolbar } returns true
@ -125,8 +128,7 @@ class BaseBrowserFragmentTest {
}
@Test
@Suppress("MaxLineLength")
fun `initializeEngineView set toolbar height as EngineView parent's bottom margin if bottom toolbar`() {
fun `initializeEngineView should set toolbar height as EngineView parent's bottom margin if bottom toolbar is forced for a11y`() {
every { settings.shouldUseBottomToolbar } returns true
every { settings.shouldUseFixedTopToolbar } returns true
@ -134,6 +136,69 @@ class BaseBrowserFragmentTest {
verify { (swipeRefreshLayout.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 13 }
}
@Test
fun `WHEN status is equals to FAILED or COMPLETED and it is the same tab then shouldShowCompletedDownloadDialog will be true`() {
every { fragment.getCurrentTab() } returns createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
)
val status = DownloadState.Status.values()
.filter { it == DownloadState.Status.COMPLETED && it == DownloadState.Status.FAILED }
status.forEach {
val result =
fragment.shouldShowCompletedDownloadDialog(download, it)
assertTrue(result)
}
}
@Test
fun `WHEN status is different from FAILED or COMPLETED then shouldShowCompletedDownloadDialog will be false`() {
every { fragment.getCurrentTab() } returns createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
)
val status = DownloadState.Status.values()
.filter { it != DownloadState.Status.COMPLETED && it != DownloadState.Status.FAILED }
status.forEach {
val result =
fragment.shouldShowCompletedDownloadDialog(download, it)
assertFalse(result)
}
}
@Test
fun `WHEN the tab is different from the initial one then shouldShowCompletedDownloadDialog will be false`() {
every { fragment.getCurrentTab() } returns createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "2",
destinationDirectory = "/",
)
val status = DownloadState.Status.values()
.filter { it != DownloadState.Status.COMPLETED && it != DownloadState.Status.FAILED }
status.forEach {
val result =
fragment.shouldShowCompletedDownloadDialog(download, it)
assertFalse(result)
}
}
}
private class TestBaseBrowserFragment : BaseBrowserFragment() {

@ -1,173 +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.browser
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.content.DownloadState.Status.COMPLETED
import mozilla.components.browser.state.state.content.DownloadState.Status.FAILED
import mozilla.components.browser.state.state.createTab
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
@RunWith(AndroidJUnit4::class)
class DownloadDialogUtilsTest {
@Test
@Suppress("MaxLineLength")
fun `GIVEN final status WHEN handleOnDownloadFinished try to open the file fails THEN show error message`() {
val downloadUtils = DownloadDialogUtils
val currentTab = createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = currentTab.id,
destinationDirectory = "/",
openInApp = true,
)
var dialogWasShown = false
var onCannotOpenFileWasCalled = false
downloadUtils.openFile = { _, _ -> false }
downloadUtils.handleOnDownloadFinished(
context = testContext,
downloadState = download,
downloadJobStatus = COMPLETED,
currentTab = currentTab,
onFinishedDialogShown = { dialogWasShown = true },
onCannotOpenFile = {
onCannotOpenFileWasCalled = true
},
)
assertTrue(onCannotOpenFileWasCalled)
assertFalse(dialogWasShown)
}
@Test
fun `GIVEN final status and openInApp WHEN calling handleOnDownloadFinished THEN try to open the file`() {
val downloadUtils = DownloadDialogUtils
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
openInApp = true,
)
val currentTab = createTab(id = "1", url = "")
var dialogWasShown = false
var onCannotOpenFileWasCalled = false
downloadUtils.openFile = { _, _ -> true }
downloadUtils.handleOnDownloadFinished(
context = testContext,
downloadState = download,
downloadJobStatus = COMPLETED,
currentTab = currentTab,
onFinishedDialogShown = { dialogWasShown = true },
onCannotOpenFile = {
onCannotOpenFileWasCalled = true
},
)
assertFalse(onCannotOpenFileWasCalled)
assertFalse(dialogWasShown)
}
@Test
fun `GIVEN final status WHEN calling handleOnDownloadFinished THEN show a finished download dialog`() {
val downloadUtils = DownloadDialogUtils
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
)
val currentTab = createTab(id = "1", url = "")
var dialogWasShown = false
downloadUtils.handleOnDownloadFinished(
context = testContext,
downloadState = download,
downloadJobStatus = COMPLETED,
currentTab = currentTab,
onFinishedDialogShown = { dialogWasShown = true },
onCannotOpenFile = {},
)
assertTrue(dialogWasShown)
}
@Test
fun `WHEN status is final and is same tab THEN shouldShowCompletedDownloadDialog will be true`() {
val currentTab = createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
)
val status = DownloadState.Status.values().filter { it == COMPLETED || it == FAILED }
status.forEach {
val result = DownloadDialogUtils.shouldShowCompletedDownloadDialog(
downloadState = download,
status = it,
currentTab = currentTab,
)
assertTrue(result)
}
}
@Test
fun `WHEN status is different from FAILED or COMPLETED then shouldShowCompletedDownloadDialog will be false`() {
val currentTab = createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "1",
destinationDirectory = "/",
)
val completedStatus = listOf(COMPLETED, FAILED)
val status = DownloadState.Status.values().filter { it !in completedStatus }
status.forEach {
val result = DownloadDialogUtils.shouldShowCompletedDownloadDialog(
downloadState = download,
status = it,
currentTab = currentTab,
)
assertFalse(result)
}
}
@Test
fun `WHEN the tab is different from the initial one then shouldShowCompletedDownloadDialog will be false`() {
val currentTab = createTab(id = "1", url = "")
val download = DownloadState(
url = "",
sessionId = "2",
destinationDirectory = "/",
)
val completedStatus = listOf(COMPLETED, FAILED)
val status = DownloadState.Status.values().filter { it !in completedStatus }
status.forEach {
val result =
DownloadDialogUtils.shouldShowCompletedDownloadDialog(
downloadState = download,
status = it,
currentTab = currentTab,
)
assertFalse(result)
}
}
}
Loading…
Cancel
Save