diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt index 7155c90ee..8c08a95fd 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonInternalSettingsFragment.kt @@ -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() - 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 - } } diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt index 05eeb740b..b1c54ee1f 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt @@ -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() - private val downloadsFeature = ViewBoundFeatureWrapper() - 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, 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 } } diff --git a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt index 12fa3597a..95b2246c5 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt @@ -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), diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 59999afaa..6de923a5a 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -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 diff --git a/app/src/main/java/org/mozilla/fenix/browser/DownloadDialogUtils.kt b/app/src/main/java/org/mozilla/fenix/browser/DownloadDialogUtils.kt deleted file mode 100644 index ee5926b5b..000000000 --- a/app/src/main/java/org/mozilla/fenix/browser/DownloadDialogUtils.kt +++ /dev/null @@ -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 - } -} diff --git a/app/src/main/java/org/mozilla/fenix/browser/DownloadUtils.kt b/app/src/main/java/org/mozilla/fenix/browser/DownloadUtils.kt new file mode 100644 index 000000000..ed0930f76 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/browser/DownloadUtils.kt @@ -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() + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 4c806ae86..0f6f107df 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -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, diff --git a/app/src/main/java/org/mozilla/fenix/components/DownloadStyling.kt b/app/src/main/java/org/mozilla/fenix/components/DownloadStyling.kt deleted file mode 100644 index 199f2312b..000000000 --- a/app/src/main/java/org/mozilla/fenix/components/DownloadStyling.kt +++ /dev/null @@ -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(), - ) - } -} diff --git a/app/src/main/res/layout/fragment_add_on_internal_settings.xml b/app/src/main/res/layout/fragment_add_on_internal_settings.xml index 0b3fa0573..282f5bd3b 100644 --- a/app/src/main/res/layout/fragment_add_on_internal_settings.xml +++ b/app/src/main/res/layout/fragment_add_on_internal_settings.xml @@ -13,18 +13,4 @@ android:id="@+id/addonSettingsEngineView" android:layout_width="match_parent" android:layout_height="match_parent" /> - - - - diff --git a/app/src/test/java/org/mozilla/fenix/addons/AddonPopupBaseFragmentTest.kt b/app/src/test/java/org/mozilla/fenix/addons/AddonPopupBaseFragmentTest.kt deleted file mode 100644 index 28fc9e261..000000000 --- a/app/src/test/java/org/mozilla/fenix/addons/AddonPopupBaseFragmentTest.kt +++ /dev/null @@ -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(relaxed = true) - val session = mockk(relaxed = true) - val response = mockk(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()) } - } -} diff --git a/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt b/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt index 4a7e37e36..ac0a109f9 100644 --- a/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt +++ b/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt @@ -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() { diff --git a/app/src/test/java/org/mozilla/fenix/browser/DownloadDialogUtilsTest.kt b/app/src/test/java/org/mozilla/fenix/browser/DownloadDialogUtilsTest.kt deleted file mode 100644 index fbd3d013e..000000000 --- a/app/src/test/java/org/mozilla/fenix/browser/DownloadDialogUtilsTest.kt +++ /dev/null @@ -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) - } - } -}