Revert "Bug 1861459 - Remove BrowsingModeManager usages outside of the Home Screen"

This reverts commit d5856268ec720ad0e41585a3f75201ae8d5e6755.
fenix/123.0
Matthew Tighe 4 months ago committed by mergify[bot]
parent 452f7147d0
commit bd7a90d34b

@ -93,7 +93,6 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.bindings.BrowserStoreBinding
import org.mozilla.fenix.components.metrics.BreadcrumbsRecorder
import org.mozilla.fenix.components.metrics.GrowthDataWorker
import org.mozilla.fenix.components.metrics.fonts.FontEnumerationWorker
@ -208,14 +207,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
private val externalSourceIntentProcessors by lazy {
listOf(
HomeDeepLinkIntentProcessor(this, components.appStore),
HomeDeepLinkIntentProcessor(this),
SpeechProcessingIntentProcessor(this, components.core.store),
AssistIntentProcessor(),
StartSearchIntentProcessor(),
OpenBrowserIntentProcessor(this, ::getIntentSessionId),
OpenSpecificTabIntentProcessor(this),
OpenPasswordManagerIntentProcessor(),
ReEngagementIntentProcessor(this, settings(), components.appStore),
ReEngagementIntentProcessor(this, settings()),
)
}
@ -379,7 +378,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
extensionsProcessDisabledBackgroundController,
serviceWorkerSupport,
webExtensionPromptFeature,
BrowserStoreBinding(components.core.store, components.appStore),
)
if (shouldAddToRecentsScreen(intent)) {

@ -24,6 +24,7 @@ import mozilla.components.feature.addons.AddonManager
import mozilla.components.feature.addons.AddonManagerException
import mozilla.components.feature.addons.ui.translateName
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.FragmentInstalledAddOnDetailsBinding
import org.mozilla.fenix.ext.components
@ -262,7 +263,7 @@ class InstalledAddonDetailsFragment : Fragment() {
private fun bindReportButton() {
binding.reportAddOn.setOnClickListener {
val shouldCreatePrivateSession = it.context.components.appStore.state.mode.isPrivate
val shouldCreatePrivateSession = (activity as HomeActivity).browsingModeManager.mode.isPrivate
it.context.components.useCases.tabsUseCases.selectOrAddTab(
url = "${BuildConfig.AMO_BASE_URL}/android/feedback/addon/${addon.id}/",
@ -285,7 +286,7 @@ class InstalledAddonDetailsFragment : Fragment() {
val directions = if (addon.installedState?.openOptionsPageInTab == true) {
val components = it.context.components
val shouldCreatePrivateSession =
components.appStore.state.mode.isPrivate
(activity as HomeActivity).browsingModeManager.mode.isPrivate
// If the addon settings page is already open in a tab, select that one
components.useCases.tabsUseCases.selectOrAddTab(

@ -2,7 +2,7 @@
* 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.appstate.bindings
package org.mozilla.fenix.bindings
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest

@ -361,12 +361,11 @@ abstract class BaseBrowserFragment :
val readerMenuController = DefaultReaderModeController(
readerViewFeature,
binding.readerViewControlsBar,
isPrivate = requireComponents.appStore.state.mode.isPrivate,
isPrivate = activity.browsingModeManager.mode.isPrivate,
onReaderModeChanged = { activity.finishActionMode() },
)
val browserToolbarController = DefaultBrowserToolbarController(
store = store,
appStore = requireComponents.appStore,
tabsUseCases = requireComponents.useCases.tabsUseCases,
activity = activity,
navController = findNavController(),
@ -380,7 +379,7 @@ abstract class BaseBrowserFragment :
findNavController().nav(
R.id.browserFragment,
BrowserFragmentDirections.actionGlobalTabsTrayFragment(
page = when (requireComponents.appStore.state.mode) {
page = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> Page.NormalTabs
BrowsingMode.Private -> Page.PrivateTabs
},
@ -1160,6 +1159,7 @@ abstract class BaseBrowserFragment :
@VisibleForTesting
internal fun observeRestoreComplete(store: BrowserStore, navController: NavController) {
val activity = activity as HomeActivity
consumeFlow(store) { flow ->
flow.map { state -> state.restoreComplete }
.distinctUntilChanged()
@ -1168,7 +1168,7 @@ abstract class BaseBrowserFragment :
// Once tab restoration is complete, if there are no tabs to show in the browser, go home
val tabs =
store.state.getNormalOrPrivateTabs(
requireComponents.appStore.state.mode.isPrivate,
activity.browsingModeManager.mode.isPrivate,
)
if (tabs.isEmpty() || store.state.selectedTabId == null) {
navController.popBackStack(R.id.homeFragment, false)
@ -1214,6 +1214,10 @@ abstract class BaseBrowserFragment :
}
private fun handleTabSelected(selectedTab: TabSessionState) {
if (!this.isRemoving) {
updateThemeForSession(selectedTab)
}
if (browserInitialized) {
view?.let {
fullScreenChanged(false)
@ -1404,6 +1408,15 @@ abstract class BaseBrowserFragment :
}
}
/**
* Set the activity normal/private theme to match the current session.
*/
@VisibleForTesting
internal fun updateThemeForSession(session: SessionState) {
val sessionMode = BrowsingMode.fromBoolean(session.content.private)
(activity as HomeActivity).browsingModeManager.mode = sessionMode
}
@VisibleForTesting
internal fun getCurrentTab(): SessionState? {
return requireComponents.core.store.state.findCustomTabOrSelectedTab(customTabSessionId)

@ -34,6 +34,7 @@ import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.GleanMetrics.ReaderMode
import org.mozilla.fenix.GleanMetrics.Shopping
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.TabCollectionStorage
@ -95,7 +96,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
)
}
val isPrivate = components.appStore.state.mode.isPrivate
val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate
val leadingAction = if (isPrivate && context.settings().feltPrivateBrowsingEnabled) {
BrowserToolbar.Button(
imageDrawable = AppCompatResources.getDrawable(

@ -32,15 +32,6 @@ import org.mozilla.fenix.wallpapers.Wallpaper
* [Action] implementation related to [AppStore].
*/
sealed class AppAction : Action {
/**
* NOTE: This action is not yet functional and will require https://bugzilla.mozilla.org/show_bug.cgi?id=1845409
* to be resolved. This is part of an ongoing lib-state refactor.
* Open a tab in the browser.
*
* @property mode Which [BrowsingMode] the tab should be opened in.
*/
data class OpenTabInBrowser(val mode: BrowsingMode) : AppAction()
data class UpdateInactiveExpanded(val expanded: Boolean) : AppAction()
/**
@ -274,24 +265,4 @@ sealed class AppAction : Action {
val key: ShoppingState.ProductRecommendationImpressionKey,
) : ShoppingAction()
}
/**
* Actions related to the home screen.
*/
sealed class HomeAction : AppAction() {
/**
* App should be opened to the home screen in [mode].
*/
data class OpenToHome(val mode: BrowsingMode) : HomeAction()
}
/**
* Actions related to Intents.
*/
sealed class IntentAction : AppAction() {
/**
* Private browsing mode should be entered.
*/
object EnterPrivateBrowsing : IntentAction()
}
}

@ -13,8 +13,6 @@ import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.shopping.ShoppingStateReducer
import org.mozilla.fenix.ext.filterOutTab
import org.mozilla.fenix.ext.getFilteredStories
import org.mozilla.fenix.home.HomeReducer
import org.mozilla.fenix.home.intent.IntentReducer
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem
@ -27,7 +25,6 @@ import org.mozilla.fenix.messaging.state.MessagingReducer
internal object AppStoreReducer {
@Suppress("LongMethod")
fun reduce(state: AppState, action: AppAction): AppState = when (action) {
is AppAction.OpenTabInBrowser -> state.copy(mode = action.mode)
is AppAction.UpdateInactiveExpanded ->
state.copy(inactiveTabsExpanded = action.expanded)
is AppAction.UpdateFirstFrameDrawn -> {
@ -242,8 +239,6 @@ internal object AppStoreReducer {
)
is AppAction.ShoppingAction -> ShoppingStateReducer.reduce(state, action)
is AppAction.HomeAction -> HomeReducer.reduce(state, action)
is AppAction.IntentAction -> IntentReducer.reduce(state, action)
}
}

@ -25,8 +25,6 @@ import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions
import org.mozilla.fenix.browser.BrowserFragmentDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.readermode.ReaderModeController
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.toolbar.interactor.BrowserToolbarInteractor
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
@ -78,7 +76,6 @@ private const val MAX_DISPLAY_NUMBER_SHOPPING_CFR = 3
@Suppress("LongParameterList")
class DefaultBrowserToolbarController(
private val store: BrowserStore,
private val appStore: AppStore,
private val tabsUseCases: TabsUseCases,
private val activity: HomeActivity,
private val navController: NavController,
@ -178,13 +175,13 @@ class DefaultBrowserToolbarController(
}
}
is TabCounterMenu.Item.NewTab -> {
appStore.dispatch(AppAction.HomeAction.OpenToHome(BrowsingMode.Normal))
activity.browsingModeManager.mode = BrowsingMode.Normal
navController.navigate(
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true),
)
}
is TabCounterMenu.Item.NewPrivateTab -> {
appStore.dispatch(AppAction.HomeAction.OpenToHome(BrowsingMode.Private))
activity.browsingModeManager.mode = BrowsingMode.Private
navController.navigate(
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true),
)

@ -563,13 +563,9 @@ class HomeFragment : Fragment() {
tabCounterView = TabCounterView(
context = requireContext(),
browsingModeManager = browsingModeManager,
navController = findNavController(),
tabCounter = binding.tabButton,
mode = requireComponents.appStore.state.mode,
itemTapped = {
newMode ->
requireComponents.appStore.dispatch(AppAction.HomeAction.OpenToHome(newMode))
},
)
toolbarView?.build()

@ -1,21 +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.home
import org.mozilla.fenix.components.appstate.AppAction.HomeAction
import org.mozilla.fenix.components.appstate.AppState
/**
* Reducer to handle updating [AppState] with the result of an [HomeAction].
*/
object HomeReducer {
/**
* Reducer to handle updating [AppState] with the result of an [HomeAction].
*/
fun reduce(state: AppState, action: HomeAction): AppState = when (action) {
is HomeAction.OpenToHome -> state.copy(mode = action.mode)
}
}

@ -17,6 +17,7 @@ import org.mozilla.fenix.GleanMetrics.StartOnHome
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.components.toolbar.FenixTabCounterMenu
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.settings
@ -26,24 +27,22 @@ import org.mozilla.fenix.tabstray.Page
* Helper class for building the [FenixTabCounterMenu].
*
* @param context An Android [Context].
* @param browsingModeManager [BrowsingModeManager] used for fetching the current browsing mode.
* @param navController [NavController] used for navigation.
* @param tabCounter The [TabCounter] that will be setup with event handlers.
* @param mode The current [BrowsingMode].
* @param itemTapped Callback to update the [BrowsingMode].
*/
class TabCounterView(
private val context: Context,
private val browsingModeManager: BrowsingModeManager,
private val navController: NavController,
private val tabCounter: TabCounter,
private val mode: BrowsingMode,
private val itemTapped: (BrowsingMode) -> Unit,
) {
init {
val tabCounterMenu = FenixTabCounterMenu(
context = context,
onItemTapped = ::onItemTapped,
iconColor = if (mode == BrowsingMode.Private) {
iconColor = if (browsingModeManager.mode == BrowsingMode.Private) {
ContextCompat.getColor(context, R.color.fx_mobile_private_text_color_primary)
} else {
null
@ -51,7 +50,7 @@ class TabCounterView(
)
tabCounterMenu.updateMenu(
showOnly = when (mode) {
showOnly = when (browsingModeManager.mode) {
BrowsingMode.Normal -> BrowsingMode.Private
BrowsingMode.Private -> BrowsingMode.Normal
},
@ -68,7 +67,7 @@ class TabCounterView(
navController.nav(
navController.currentDestination?.id,
NavGraphDirections.actionGlobalTabsTrayFragment(
page = when (mode) {
page = when (browsingModeManager.mode) {
BrowsingMode.Normal -> Page.NormalTabs
BrowsingMode.Private -> Page.PrivateTabs
},
@ -84,7 +83,7 @@ class TabCounterView(
* browsing mode.
*/
fun update(browserState: BrowserState) {
val isPrivate = mode.isPrivate
val isPrivate = browsingModeManager.mode.isPrivate
val tabCount = if (isPrivate) {
browserState.privateTabs.size
} else {
@ -103,9 +102,9 @@ class TabCounterView(
*/
internal fun onItemTapped(item: TabCounterMenu.Item) {
if (item is TabCounterMenu.Item.NewTab) {
itemTapped(BrowsingMode.Normal)
browsingModeManager.mode = BrowsingMode.Normal
} else if (item is TabCounterMenu.Item.NewPrivateTab) {
itemTapped(BrowsingMode.Private)
browsingModeManager.mode = BrowsingMode.Private
}
}
}

@ -17,8 +17,7 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.GlobalDirections
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.alreadyOnDestination
import org.mozilla.fenix.ext.openSetDefaultBrowserOption
@ -27,7 +26,6 @@ import org.mozilla.fenix.ext.openSetDefaultBrowserOption
*/
class HomeDeepLinkIntentProcessor(
private val activity: HomeActivity,
private val appStore: AppStore,
) : HomeIntentProcessor {
private val logger = Logger("DeepLinkIntentProcessor")
@ -78,7 +76,7 @@ class HomeDeepLinkIntentProcessor(
private fun handleDeepLinkSideEffects(deepLink: Uri) {
when (deepLink.host) {
"enable_private_browsing" -> {
appStore.dispatch(AppAction.IntentAction.EnterPrivateBrowsing)
activity.browsingModeManager.mode = BrowsingMode.Private
}
"make_default_browser" -> {
activity.openSetDefaultBrowserOption(

@ -1,22 +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.home.intent
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.appstate.AppAction.IntentAction
import org.mozilla.fenix.components.appstate.AppState
/**
* Reducer to handle updating [AppState] with the result of an [IntentAction].
*/
object IntentReducer {
/**
* Reducer to handle updating [AppState] with the result of an [IntentAction].
*/
fun reduce(state: AppState, action: IntentAction): AppState = when (action) {
is IntentAction.EnterPrivateBrowsing -> state.copy(mode = BrowsingMode.Private)
}
}

@ -15,8 +15,6 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.onboarding.ReEngagementNotificationWorker
import org.mozilla.fenix.onboarding.ReEngagementNotificationWorker.Companion.isReEngagementNotificationIntent
@ -32,7 +30,6 @@ import org.mozilla.fenix.utils.Settings
class ReEngagementIntentProcessor(
private val activity: HomeActivity,
private val settings: Settings,
private val appStore: AppStore,
) : HomeIntentProcessor {
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
@ -49,7 +46,7 @@ class ReEngagementIntentProcessor(
navController.nav(null, directions, options)
}
else -> {
appStore.dispatch(AppAction.OpenTabInBrowser(BrowsingMode.Private))
activity.browsingModeManager.mode = BrowsingMode.Private
activity.openToBrowserAndLoad(
ReEngagementNotificationWorker.NOTIFICATION_TARGET_URL,
newTab = true,

@ -276,7 +276,7 @@ class DefaultSessionControlController(
TopSites.openInPrivateTab.record(NoExtras())
}
with(activity) {
appStore.dispatch(AppAction.ModeChange(BrowsingMode.Private))
browsingModeManager.mode = BrowsingMode.Private
openToBrowserAndLoad(
searchTermOrURL = topSite.url,
newTab = true,
@ -464,7 +464,7 @@ class DefaultSessionControlController(
}
override fun handleShowWallpapersOnboardingDialog(state: WallpaperState): Boolean {
return if (appStore.state.mode.isPrivate) {
return if (activity.browsingModeManager.mode.isPrivate) {
false
} else {
state.availableWallpapers.filter { wallpaper ->
@ -504,7 +504,7 @@ class DefaultSessionControlController(
registerCollectionStorageObserver()
val tabIds = store.state
.getNormalOrPrivateTabs(private = appStore.state.mode.isPrivate)
.getNormalOrPrivateTabs(private = activity.browsingModeManager.mode.isPrivate)
.map { session -> session.id }
.toList()
.toTypedArray()

@ -8,7 +8,9 @@ import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.setToolbarColors
@ -30,6 +32,8 @@ abstract class LibraryPageFragment<T> : Fragment() {
tabsUseCases.addTab.invoke(url, private = private)
}
}
(activity as HomeActivity).browsingModeManager.mode = BrowsingMode.fromBoolean(private)
}
override fun onDetach() {

@ -24,7 +24,6 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
@ -78,7 +77,6 @@ class DefaultBookmarkController(
private val clipboardManager: ClipboardManager?,
private val scope: CoroutineScope,
private val store: BookmarkFragmentStore,
private val appStore: AppStore,
private val sharedViewModel: BookmarksSharedViewModel,
private val tabsUseCases: TabsUseCases?,
private val loadBookmarkNode: suspend (String, Boolean) -> BookmarkNode?,
@ -99,12 +97,13 @@ class DefaultBookmarkController(
override fun handleBookmarkTapped(item: BookmarkNode) {
val fromHomeFragment =
navController.previousBackStackEntry?.destination?.id == R.id.homeFragment
val isPrivate = appStore.state.mode == BrowsingMode.Private
val isPrivate = activity.browsingModeManager.mode == BrowsingMode.Private
val flags = EngineSession.LoadUrlFlags.select(EngineSession.LoadUrlFlags.ALLOW_JAVASCRIPT_URL)
openInNewTabAndShow(
item.url!!,
isPrivate || fromHomeFragment,
BrowserDirection.FromBookmarks,
activity.browsingModeManager.mode,
flags,
)
}
@ -196,6 +195,8 @@ class DefaultBookmarkController(
startLoading = load,
)
}
activity.browsingModeManager.mode =
BrowsingMode.fromBoolean(mode == BrowsingMode.Private)
showTabTray(mode.isPrivate)
}
@ -263,15 +264,20 @@ class DefaultBookmarkController(
searchTermOrURL: String,
newTab: Boolean,
from: BrowserDirection,
mode: BrowsingMode,
flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(),
) {
activity.openToBrowserAndLoad(searchTermOrURL, newTab, from, flags = flags)
with(activity) {
browsingModeManager.mode = mode
openToBrowserAndLoad(searchTermOrURL, newTab, from, flags = flags)
}
}
private fun openInNewTab(
url: String,
mode: BrowsingMode,
) {
activity.browsingModeManager.mode = BrowsingMode.fromBoolean(mode == BrowsingMode.Private)
tabsUseCases?.addTab?.invoke(url, private = (mode == BrowsingMode.Private))
}

@ -99,7 +99,6 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
clipboardManager = requireContext().getSystemService(),
scope = viewLifecycleOwner.lifecycleScope,
store = bookmarkStore,
appStore = requireComponents.appStore,
sharedViewModel = sharedViewModel,
tabsUseCases = activity?.components?.useCases?.tabsUseCases,
loadBookmarkNode = ::loadBookmarkNode,

@ -4,11 +4,10 @@
package org.mozilla.fenix.library.downloads
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
interface DownloadController {
/**
* Handle opening a [DownloadItem].
*/
fun handleOpen(item: DownloadItem)
fun handleOpen(item: DownloadItem, mode: BrowsingMode? = null)
fun handleSelect(item: DownloadItem)
fun handleDeselect(item: DownloadItem)
fun handleBackPressed(): Boolean
@ -18,12 +17,12 @@ interface DownloadController {
class DefaultDownloadController(
private val store: DownloadFragmentStore,
private val openToFileManager: (item: DownloadItem) -> Unit,
private val openToFileManager: (item: DownloadItem, mode: BrowsingMode?) -> Unit,
private val invalidateOptionsMenu: () -> Unit,
private val deleteDownloadItems: (Set<DownloadItem>) -> Unit,
) : DownloadController {
override fun handleOpen(item: DownloadItem) {
openToFileManager(item)
override fun handleOpen(item: DownloadItem, mode: BrowsingMode?) {
openToFileManager(item, mode)
}
override fun handleSelect(item: DownloadItem) {

@ -26,10 +26,11 @@ import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.feature.downloads.AbstractFetchDownloadService
import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.UserInteractionHandler
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.components
import org.mozilla.fenix.databinding.FragmentDownloadsBinding
import org.mozilla.fenix.downloads.DynamicDownloadDialog
import org.mozilla.fenix.ext.components
@ -210,7 +211,8 @@ class DownloadFragment : LibraryPageFragment<DownloadItem>(), UserInteractionHan
return downloadView.onBackPressed()
}
private fun openItem(item: DownloadItem) {
private fun openItem(item: DownloadItem, mode: BrowsingMode? = null) {
mode?.let { (activity as HomeActivity).browsingModeManager.mode = it }
context?.let {
val contentLength = if (item.size.isNotEmpty()) {
item.size.toLong()

@ -317,7 +317,10 @@ class HistoryFragment : LibraryPageFragment<History>(), UserInteractionHandler,
(selectedItem as? History.Regular)?.url ?: (selectedItem as? History.Metadata)?.url
}
(activity as HomeActivity).supportActionBar?.hide()
(activity as HomeActivity).apply {
browsingModeManager.mode = BrowsingMode.Private
supportActionBar?.hide()
}
showTabTray(openInPrivate = true)
historyStore.dispatch(HistoryFragmentAction.ExitEditMode)
@ -385,7 +388,7 @@ class HistoryFragment : LibraryPageFragment<History>(), UserInteractionHandler,
GleanHistory.OpenedItemExtra(
isRemote = item.isRemote,
timeGroup = item.historyTimeGroup.toString(),
isPrivate = requireComponents.appStore.state.mode == BrowsingMode.Private,
isPrivate = (activity as HomeActivity).browsingModeManager.mode == BrowsingMode.Private,
),
)

@ -32,6 +32,7 @@ import mozilla.components.ui.widgets.withCenterAlignedButtons
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.addons.showSnackBar
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.databinding.FragmentHistoryMetadataGroupBinding
import org.mozilla.fenix.ext.components
@ -187,7 +188,10 @@ class HistoryMetadataGroupFragment :
selectedItem.url
}
(activity as HomeActivity).supportActionBar?.hide()
(activity as HomeActivity).apply {
browsingModeManager.mode = BrowsingMode.Private
supportActionBar?.hide()
}
showTabTray(openInPrivate = true)
true

@ -29,7 +29,6 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.databinding.FragmentRecentlyClosedTabsBinding
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.setTextColor
@ -139,7 +138,7 @@ class RecentlyClosedFragment :
}
private fun openItem(url: String, mode: BrowsingMode? = null) {
mode?.let { requireComponents.appStore.dispatch(AppAction.OpenTabInBrowser(it)) }
mode?.let { (activity as HomeActivity).browsingModeManager.mode = it }
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = url,

@ -25,7 +25,6 @@ import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.UnifiedSearch
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.Core
import org.mozilla.fenix.components.metrics.MetricsUtils
import org.mozilla.fenix.crashes.CrashListActivity
@ -63,7 +62,6 @@ interface SearchController {
class SearchDialogController(
private val activity: HomeActivity,
private val store: BrowserStore,
private val appStore: AppStore,
private val tabsUseCases: TabsUseCases,
private val fragmentStore: SearchFragmentStore,
private val navController: NavController,
@ -159,7 +157,7 @@ class SearchDialogController(
fragmentStore.dispatch(
SearchFragmentAction.AllowSearchSuggestionsInPrivateModePrompt(
text.isNotEmpty() &&
appStore.state.mode.isPrivate &&
activity.browsingModeManager.mode.isPrivate &&
settings.shouldShowSearchSuggestions &&
!settings.shouldShowSearchSuggestionsInPrivate &&
!settings.showSearchSuggestionsInPrivateOnboardingFinished,
@ -230,7 +228,7 @@ class SearchDialogController(
fragmentStore.dispatch(
SearchFragmentAction.SearchDefaultEngineSelected(
engine = searchEngine,
browsingMode = appStore.state.mode,
browsingMode = activity.browsingModeManager.mode,
settings = settings,
),
)
@ -239,7 +237,7 @@ class SearchDialogController(
fragmentStore.dispatch(
SearchFragmentAction.SearchShortcutEngineSelected(
engine = searchEngine,
browsingMode = appStore.state.mode,
browsingMode = activity.browsingModeManager.mode,
settings = settings,
),
)

@ -177,7 +177,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
this@SearchDialogFragment.onBackPressed()
}
}.apply {
if (requireComponents.appStore.state.mode.isPrivate) {
if ((requireActivity() as HomeActivity).browsingModeManager.mode.isPrivate) {
this.secure(requireActivity())
}
}
@ -193,10 +193,11 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
val args by navArgs<SearchDialogFragmentArgs>()
_binding = FragmentSearchDialogBinding.inflate(inflater, container, false)
val activity = requireActivity() as HomeActivity
val isPrivate = requireComponents.appStore.state.mode.isPrivate
val isPrivate = activity.browsingModeManager.mode.isPrivate
store = SearchDialogFragmentStore(
createInitialSearchFragmentState(
activity,
requireComponents,
tabId = args.sessionId,
pastedText = args.pastedText,
@ -211,7 +212,6 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
SearchDialogController(
activity = activity,
store = requireComponents.core.store,
appStore = requireComponents.appStore,
tabsUseCases = requireComponents.useCases.tabsUseCases,
fragmentStore = store,
navController = findNavController(),
@ -904,7 +904,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
} else {
val clipboardUrl = context?.components?.clipboardHandler?.extractURL()
if (clipboardUrl != null && !(requireComponents.appStore.state.mode.isPrivate)) {
if (clipboardUrl != null && !((activity as HomeActivity).browsingModeManager.mode.isPrivate)) {
requireComponents.core.engine.speculativeConnect(clipboardUrl)
}
binding.clipboardUrl.text = clipboardUrl

@ -13,6 +13,7 @@ import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
import mozilla.components.lib.state.Action
import mozilla.components.lib.state.State
import mozilla.components.lib.state.Store
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.metrics.MetricsUtils
@ -141,6 +142,7 @@ data class SearchFragmentState(
* Creates the initial state for the search fragment.
*/
fun createInitialSearchFragmentState(
activity: HomeActivity,
components: Components,
tabId: String?,
pastedText: String?,
@ -164,7 +166,7 @@ fun createInitialSearchFragmentState(
searchEngineSource = searchEngineSource,
defaultEngine = null,
showSearchSuggestions = shouldShowSearchSuggestions(
browsingMode = components.appStore.state.mode,
browsingMode = activity.browsingModeManager.mode,
settings = settings,
),
showSearchSuggestionsHint = false,
@ -181,9 +183,9 @@ fun createInitialSearchFragmentState(
showAllSyncedTabsSuggestions = settings.shouldShowSyncedTabsSuggestions,
showSessionSuggestionsForCurrentEngine = false,
showAllSessionSuggestions = true,
showSponsoredSuggestions = components.appStore.state.mode == BrowsingMode.Normal &&
showSponsoredSuggestions = activity.browsingModeManager.mode == BrowsingMode.Normal &&
settings.enableFxSuggest && settings.showSponsoredSuggestions,
showNonSponsoredSuggestions = components.appStore.state.mode == BrowsingMode.Normal &&
showNonSponsoredSuggestions = activity.browsingModeManager.mode == BrowsingMode.Normal &&
settings.enableFxSuggest && settings.showNonSponsoredSuggestions,
tabId = tabId,
pastedText = pastedText,

@ -117,7 +117,7 @@ class AwesomeBarView(
init {
val primaryTextColor = activity.getColorFromAttr(R.attr.textPrimary)
engineForSpeculativeConnects = when (components.appStore.state.mode) {
engineForSpeculativeConnects = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> components.core.engine
BrowsingMode.Private -> null
}
@ -162,7 +162,7 @@ class AwesomeBarView(
showDescription = false,
engine = engineForSpeculativeConnects,
filterExactMatch = true,
private = when (components.appStore.state.mode) {
private = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> false
BrowsingMode.Private -> true
},
@ -328,12 +328,12 @@ class AwesomeBarView(
}
}
if (components.appStore.state.mode == BrowsingMode.Normal && state.showAllSessionSuggestions) {
if (activity.browsingModeManager.mode == BrowsingMode.Normal && state.showAllSessionSuggestions) {
// Unlike other providers, we don't exclude sponsored suggestions for open tabs.
providersToAdd.add(getLocalTabsProvider())
}
if (components.appStore.state.mode == BrowsingMode.Normal && state.showSessionSuggestionsForCurrentEngine) {
if (activity.browsingModeManager.mode == BrowsingMode.Normal && state.showSessionSuggestionsForCurrentEngine) {
getFilterForCurrentEngineResults(state)?.let {
providersToAdd.add(getLocalTabsProvider(it))
}
@ -448,7 +448,7 @@ class AwesomeBarView(
colorFilter = createBlendModeColorFilterCompat(primaryTextColor, SRC_IN)
}.toBitmap()
val engineForSpeculativeConnects = when (components.appStore.state.mode) {
val engineForSpeculativeConnects = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> components.core.engine
BrowsingMode.Private -> null
}
@ -469,7 +469,7 @@ class AwesomeBarView(
icon = searchBitmap,
engine = engineForSpeculativeConnects,
filterExactMatch = true,
private = when (components.appStore.state.mode) {
private = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> false
BrowsingMode.Private -> true
},

@ -9,9 +9,9 @@ import android.view.WindowManager
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.PrivateShortcutCreateManager
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
@ -45,7 +45,9 @@ class PrivateBrowsingFragment : PreferenceFragmentCompat() {
requirePreference<SwitchPreference>(R.string.pref_key_allow_screenshots_in_private_mode).apply {
onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
if (requireComponents.appStore.state.mode.isPrivate && newValue == false) {
if ((activity as? HomeActivity)?.browsingModeManager?.mode?.isPrivate == true &&
newValue == false
) {
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)

@ -23,7 +23,6 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
@ -110,10 +109,8 @@ class WallpaperSettingsFragment : Fragment() {
)
.setText(view.context.getString(R.string.wallpaper_updated_snackbar_message))
.setAction(requireContext().getString(R.string.wallpaper_updated_snackbar_action)) {
requireComponents.appStore.dispatch(
AppAction.HomeAction.OpenToHome(BrowsingMode.Normal),
)
findNavController().popBackStack(R.id.homeFragment, false)
(activity as HomeActivity).browsingModeManager.mode = BrowsingMode.Normal
findNavController().navigate(R.id.homeFragment)
}
.show()

@ -9,7 +9,7 @@ import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayout
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.support.base.feature.LifecycleAwareFeature
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_NORMAL_TABS
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_PRIVATE_TABS
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_SYNCED_TABS
@ -22,7 +22,7 @@ class TabLayoutMediator(
private val tabLayout: TabLayout,
private val tabPager: ViewPager2,
interactor: TabsTrayInteractor,
private val appStore: AppStore,
private val browsingModeManager: BrowsingModeManager,
private val tabsTrayStore: TabsTrayStore,
) : LifecycleAwareFeature {
@ -45,7 +45,7 @@ class TabLayoutMediator(
internal fun selectActivePage() {
val selectedPagerPosition =
when {
appStore.state.mode.isPrivate -> POSITION_PRIVATE_TABS
browsingModeManager.mode.isPrivate -> POSITION_PRIVATE_TABS
tabsTrayStore.state.selectedPage == Page.SyncedTabs -> POSITION_SYNCED_TABS
else -> POSITION_NORMAL_TABS
}

@ -32,6 +32,7 @@ import org.mozilla.fenix.GleanMetrics.TabsTray
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.collections.CollectionsDialog
import org.mozilla.fenix.collections.show
import org.mozilla.fenix.components.AppStore
@ -177,6 +178,7 @@ interface TabsTrayController : SyncedTabsController, InactiveTabsController, Tab
* @param tabsTrayStore [TabsTrayStore] used to read/update the [TabsTrayState].
* @param browserStore [BrowserStore] used to read/update the current [BrowserState].
* @param settings [Settings] used to update any user preferences.
* @param browsingModeManager [BrowsingModeManager] used to read/update the current [BrowsingMode].
* @param navController [NavController] used to navigate away from the tabs tray.
* @param navigateToHomeAndDeleteSession Lambda used to return to the Homescreen and delete the current session.
* @param profiler [Profiler] used to add profiler markers.
@ -201,6 +203,7 @@ class DefaultTabsTrayController(
private val tabsTrayStore: TabsTrayStore,
private val browserStore: BrowserStore,
private val settings: Settings,
private val browsingModeManager: BrowsingModeManager,
private val navController: NavController,
private val navigateToHomeAndDeleteSession: (String) -> Unit,
private val profiler: Profiler?,
@ -242,7 +245,7 @@ class DefaultTabsTrayController(
*/
private fun openNewTab(isPrivate: Boolean) {
val startTime = profiler?.getProfilerTime()
appStore.dispatch(AppAction.HomeAction.OpenToHome(BrowsingMode.fromBoolean(isPrivate)))
browsingModeManager.mode = BrowsingMode.fromBoolean(isPrivate)
navController.navigate(
TabsTrayFragmentDirections.actionGlobalHome(focusOnAddressBar = true),
)
@ -533,6 +536,7 @@ class DefaultTabsTrayController(
selected.isEmpty() && tabsTrayStore.state.mode.isSelect().not() -> {
TabsTray.openedExistingTab.record(TabsTray.OpenedExistingTabExtra(source ?: "unknown"))
tabsUseCases.selectTab(tab.id)
browsingModeManager.mode = BrowsingMode.fromBoolean(tab.content.private)
handleNavigateToBrowser()
}
tab.id in selected.map { it.id } -> handleTabUnselected(tab)

@ -175,6 +175,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsTrayStore = tabsTrayStore,
browserStore = requireComponents.core.store,
settings = requireContext().settings(),
browsingModeManager = activity.browsingModeManager,
navController = findNavController(),
navigateToHomeAndDeleteSession = ::navigateToHomeAndDeleteSession,
navigationInteractor = navigationInteractor,
@ -409,6 +410,8 @@ class TabsTrayFragment : AppCompatDialogFragment() {
}
if (!requireContext().settings().enableTabsTrayToCompose) {
val activity = activity as HomeActivity
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
fabButtonBinding.newTabButton.accessibilityTraversalAfter =
tabsTrayBinding.tabLayout.id
@ -439,7 +442,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabLayout = tabsTrayBinding.tabLayout,
tabPager = tabsTrayBinding.tabsTray,
interactor = tabsTrayInteractor,
appStore = requireComponents.appStore,
browsingModeManager = activity.browsingModeManager,
tabsTrayStore = tabsTrayStore,
),
owner = this,

@ -8,7 +8,6 @@ import android.app.Activity
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
import android.net.Uri
import androidx.core.text.isDigitsOnly
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify
@ -60,7 +59,6 @@ class IntentReceiverActivityTest {
mockkStatic("org.mozilla.fenix.ext.ContextKt")
settings = mockk()
intentProcessors = mockk()
"".isDigitsOnly()
every { settings.openLinksInAPrivateTab } returns false
every { intentProcessors.intentProcessor } returns mockIntentProcessor()

@ -24,7 +24,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.databinding.FragmentInstalledAddOnDetailsBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -159,7 +158,6 @@ class InstalledAddonDetailsFragmentTest {
every { selectOrAddTab.invoke(any(), any(), any(), any(), any()) } returns "some-tab-id"
every { useCases.selectOrAddTab } returns selectOrAddTab
every { testContext.components.useCases.tabsUseCases } returns useCases
every { testContext.components.appStore.state.mode } returns BrowsingMode.Normal
// We create the `binding` instance and bind the UI here because `onCreateView()` checks a late init variable
// and we cannot easily mock it to skip the check.
fragment.setBindingAndBindUI(
@ -194,22 +192,21 @@ class InstalledAddonDetailsFragmentTest {
val addon = mockAddon()
every { fragment.addon } returns addon
val homeActivity = mockk<HomeActivity>(relaxed = true)
every { homeActivity.browsingModeManager.mode.isPrivate } returns true
every { fragment.activity } returns homeActivity
val useCases = mockk<TabsUseCases>()
val selectOrAddTab = mockk<TabsUseCases.SelectOrAddUseCase>()
every { selectOrAddTab.invoke(any(), any(), any(), any(), any()) } returns "some-tab-id"
every { useCases.selectOrAddTab } returns selectOrAddTab
every { testContext.components.useCases.tabsUseCases } returns useCases
every { testContext.components.appStore.state.mode } returns BrowsingMode.Private
// We create the `binding` instance and bind the UI here because `onCreateView()` checks a late init variable
// and we cannot easily mock it to skip the check.
val binding = FragmentInstalledAddOnDetailsBinding.inflate(
LayoutInflater.from(testContext),
mockk(relaxed = true),
false,
)
fragment.setBindingAndBindUI(
binding,
FragmentInstalledAddOnDetailsBinding.inflate(
LayoutInflater.from(testContext),
mockk(relaxed = true),
false,
),
)
val navController = mockk<NavController>(relaxed = true)
Navigation.setViewNavController(fragment.binding.root, navController)

@ -11,11 +11,11 @@ import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.appstate.bindings.BrowserStoreBinding
class BrowserStoreBindingTest {

@ -40,7 +40,6 @@ import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.FenixApplication
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.toolbar.BrowserToolbarView
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
import org.mozilla.fenix.ext.application
@ -55,7 +54,6 @@ import org.mozilla.fenix.utils.Settings
class BrowserFragmentTest {
private lateinit var store: BrowserStore
private lateinit var appStore: AppStore
private lateinit var testTab: TabSessionState
private lateinit var browserFragment: BrowserFragment
private lateinit var view: View
@ -97,8 +95,6 @@ class BrowserFragmentTest {
testTab = createTab(url = "https://mozilla.org")
store = BrowserStore()
every { context.components.core.store } returns store
appStore = AppStore()
every { context.components.appStore } returns appStore
mockkObject(FeatureFlags)
}
@ -108,6 +104,24 @@ class BrowserFragmentTest {
unmockkObject(FeatureFlags)
}
@Test
fun `GIVEN fragment is added WHEN selected tab changes THEN theme is updated`() {
browserFragment.observeTabSelection(store)
verify(exactly = 0) { browserFragment.updateThemeForSession(testTab) }
addAndSelectTab(testTab)
verify(exactly = 1) { browserFragment.updateThemeForSession(testTab) }
}
@Test
fun `GIVEN fragment is removing WHEN selected tab changes THEN theme is not updated`() {
every { browserFragment.isRemoving } returns true
browserFragment.observeTabSelection(store)
addAndSelectTab(testTab)
verify(exactly = 0) { browserFragment.updateThemeForSession(testTab) }
}
@Test
fun `GIVEN browser UI is not initialized WHEN selected tab changes THEN browser UI is initialized`() {
browserFragment.observeTabSelection(store)

@ -20,7 +20,6 @@ import mozilla.components.service.pocket.PocketStory
import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory
import mozilla.components.service.pocket.PocketStory.PocketSponsoredStory
import mozilla.components.service.pocket.PocketStory.PocketSponsoredStoryCaps
import mozilla.components.support.test.ext.joinBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertSame
@ -539,22 +538,4 @@ class AppStoreTest {
assertEquals(recentHistory - group2, recentHistory.filterOut("Title2"))
assertEquals(recentHistory - group3, recentHistory.filterOut("title3"))
}
@Test
fun `WHEN new tab clicked THEN mode is updated to normal`() {
appStore = AppStore(AppState(mode = BrowsingMode.Private))
appStore.dispatch(AppAction.HomeAction.OpenToHome(BrowsingMode.Normal)).joinBlocking()
assertEquals(BrowsingMode.Normal, appStore.state.mode)
}
@Test
fun `WHEN new private tab clicked THEN mode is updated to private`() {
appStore = AppStore(AppState(mode = BrowsingMode.Normal))
appStore.dispatch(AppAction.HomeAction.OpenToHome(BrowsingMode.Private)).joinBlocking()
assertEquals(BrowsingMode.Private, appStore.state.mode)
}
}

@ -48,9 +48,8 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserAnimator
import org.mozilla.fenix.browser.BrowserFragmentDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.SimpleBrowsingModeManager
import org.mozilla.fenix.browser.readermode.ReaderModeController
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -93,7 +92,6 @@ class DefaultBrowserToolbarControllerTest {
@RelaxedMockK
private lateinit var homeViewModel: HomeScreenViewModel
private lateinit var appStore: AppStore
private lateinit var store: BrowserStore
private val captureMiddleware = CaptureActionsMiddleware<BrowserState, BrowserAction>()
@ -128,7 +126,6 @@ class DefaultBrowserToolbarControllerTest {
),
middleware = listOf(captureMiddleware),
)
appStore = AppStore()
}
@After
@ -316,31 +313,29 @@ class DefaultBrowserToolbarControllerTest {
@Test
fun handleToolbarNewTabPress() {
appStore = AppStore(AppState(mode = BrowsingMode.Private))
val browsingModeManager = SimpleBrowsingModeManager(BrowsingMode.Private)
val item = TabCounterMenu.Item.NewTab
every { activity.browsingModeManager } returns browsingModeManager
every { navController.navigate(BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)) } just Runs
val controller = createController()
controller.handleTabCounterItemInteraction(item)
appStore.waitUntilIdle()
assertEquals(BrowsingMode.Normal, appStore.state.mode)
assertEquals(BrowsingMode.Normal, browsingModeManager.mode)
verify { navController.navigate(BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)) }
}
@Test
fun handleToolbarNewPrivateTabPress() {
appStore = AppStore(AppState(mode = BrowsingMode.Normal))
val browsingModeManager = SimpleBrowsingModeManager(BrowsingMode.Normal)
val item = TabCounterMenu.Item.NewPrivateTab
every { activity.browsingModeManager } returns browsingModeManager
every { navController.navigate(BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)) } just Runs
val controller = createController()
controller.handleTabCounterItemInteraction(item)
appStore.waitUntilIdle()
assertEquals(BrowsingMode.Private, appStore.state.mode)
assertEquals(BrowsingMode.Private, browsingModeManager.mode)
verify { navController.navigate(BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)) }
}
@ -469,7 +464,6 @@ class DefaultBrowserToolbarControllerTest {
customTabSessionId: String? = null,
) = DefaultBrowserToolbarController(
store = store,
appStore = appStore,
tabsUseCases = tabsUseCases,
activity = activity,
navController = navController,

@ -65,6 +65,7 @@ class ExternalAppBrowserActivityTest {
every { activity.components.settings.shouldReturnToBrowser } returns true
every { activity.openToBrowser(any(), any()) } returns Unit
activity.browsingModeManager = browsingModeManager
activity.navigateToBrowserOnColdStart()
verify(exactly = 0) { activity.openToBrowser(BrowserDirection.FromGlobal, null) }

@ -1117,11 +1117,15 @@ class DefaultSessionControlControllerTest {
@Test
fun `GIVEN app is in private browsing mode WHEN handling wallpaper dialog THEN the dialog is not shown`() {
every { appStore.state.mode } returns BrowsingMode.Private
every { activity.browsingModeManager } returns mockk {
every { mode } returns mockk {
every { isPrivate } returns true
}
}
val wallpaperState = WallpaperState.default.copy(
availableWallpapers = makeFakeRemoteWallpapers(
THUMBNAILS_SELECTION_COUNT,
false,
true,
),
)

@ -18,7 +18,6 @@ import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.rule.MainCoroutineRule
import mozilla.components.support.test.rule.runTestOnMain
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.components.AppStore
@ -86,7 +85,6 @@ class PocketUpdatesMiddlewareTest {
@Test
@Suppress("UNCHECKED_CAST")
@Ignore("started failing after introduction of InitAction. https://bugzilla.mozilla.org/show_bug.cgi?id=1864986")
fun `WHEN PocketStoriesCategoriesChange is dispatched THEN intercept and dispatch PocketStoriesCategoriesSelectionsChange`() = runTestOnMain {
val persistedSelectedCategory: SelectedPocketStoriesCategory = mockk {
every { name } returns "testCategory"

@ -29,6 +29,8 @@ import org.mozilla.fenix.GleanMetrics.StartOnHome
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -41,7 +43,9 @@ class TabCounterViewTest {
val gleanTestRule = GleanTestRule(testContext)
private lateinit var navController: NavController
private lateinit var browsingModeManager: BrowsingModeManager
private lateinit var settings: Settings
private lateinit var modeDidChange: (BrowsingMode) -> Unit
private lateinit var tabCounterView: TabCounterView
private lateinit var tabCounter: TabCounter
@ -49,16 +53,30 @@ class TabCounterViewTest {
fun setup() {
navController = mockk(relaxed = true)
settings = mockk(relaxed = true)
modeDidChange = mockk(relaxed = true)
tabCounter = spyk(TabCounter(testContext))
browsingModeManager = DefaultBrowsingModeManager(
_mode = BrowsingMode.Normal,
settings = settings,
modeDidChange = modeDidChange,
)
tabCounterView = TabCounterView(
context = testContext,
browsingModeManager = browsingModeManager,
navController = navController,
tabCounter = tabCounter,
)
}
@Test
fun `WHEN tab counter is clicked THEN navigate to tabs tray and record metrics`() {
every { navController.currentDestination?.id } returns R.id.homeFragment
assertNull(StartOnHome.openTabsTray.testGetValue())
tabCounterView = createTabCounterView()
tabCounter.performClick()
assertNotNull(StartOnHome.openTabsTray.testGetValue())
@ -73,26 +91,16 @@ class TabCounterViewTest {
@Test
fun `WHEN New tab menu item is tapped THEN set browsing mode to normal`() {
var capture: BrowsingMode? = null
tabCounterView = createTabCounterView {
capture = it
}
tabCounterView.onItemTapped(TabCounterMenu.Item.NewTab)
assertEquals(BrowsingMode.Normal, capture)
assertEquals(BrowsingMode.Normal, browsingModeManager.mode)
}
@Test
fun `WHEN New private tab menu item is tapped THEN set browsing mode to private`() {
var capture: BrowsingMode? = null
tabCounterView = createTabCounterView {
capture = it
}
tabCounterView.onItemTapped(TabCounterMenu.Item.NewPrivateTab)
assertEquals(BrowsingMode.Private, capture)
assertEquals(BrowsingMode.Private, browsingModeManager.mode)
}
@Test
@ -107,7 +115,6 @@ class TabCounterViewTest {
),
selectedTabId = "mozilla",
)
tabCounterView = createTabCounterView()
tabCounterView.update(browserState)
@ -115,7 +122,7 @@ class TabCounterViewTest {
tabCounter.setCountWithAnimation(browserState.normalTabs.size)
}
tabCounterView = createTabCounterView(mode = BrowsingMode.Private)
browsingModeManager.mode = BrowsingMode.Private
tabCounterView.update(browserState)
@ -137,10 +144,10 @@ class TabCounterViewTest {
selectedTabId = "mozilla",
)
tabCounterView = createTabCounterView(mode = BrowsingMode.Private)
browsingModeManager.mode = BrowsingMode.Private
tabCounterView.update(browserState)
verify {
verifyOrder {
tabCounter.toggleCounterMask(true)
}
}
@ -158,22 +165,10 @@ class TabCounterViewTest {
selectedTabId = "mozilla",
)
tabCounterView = createTabCounterView()
tabCounterView.update(browserState)
verifyOrder {
tabCounter.toggleCounterMask(false)
}
}
private fun createTabCounterView(
mode: BrowsingMode = BrowsingMode.Normal,
itemTapped: (BrowsingMode) -> Unit = {},
) = TabCounterView(
context = testContext,
navController = navController,
tabCounter = tabCounter,
mode = mode,
itemTapped = itemTapped,
)
}

@ -14,7 +14,6 @@ import io.mockk.Called
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.Job
import mozilla.appservices.places.BookmarkRoot
import mozilla.components.concept.engine.EngineSession
import org.junit.Assert.assertFalse
@ -27,9 +26,7 @@ import org.mozilla.fenix.BuildConfig.DEEP_LINK_SCHEME
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.settings.SupportUtils
import org.robolectric.annotation.Config
@ -37,7 +34,6 @@ import org.robolectric.annotation.Config
@RunWith(FenixRobolectricTestRunner::class)
class HomeDeepLinkIntentProcessorTest {
private lateinit var activity: HomeActivity
private lateinit var appStore: AppStore
private lateinit var navController: NavController
private lateinit var out: Intent
private lateinit var processorHome: HomeDeepLinkIntentProcessor
@ -45,10 +41,9 @@ class HomeDeepLinkIntentProcessorTest {
@Before
fun setup() {
activity = mockk(relaxed = true)
appStore = mockk(relaxed = true)
navController = mockk(relaxed = true)
out = mockk()
processorHome = HomeDeepLinkIntentProcessor(activity, appStore)
processorHome = HomeDeepLinkIntentProcessor(activity)
}
@Test
@ -196,11 +191,9 @@ class HomeDeepLinkIntentProcessorTest {
@Test
fun `process enable_private_browsing deep link`() {
every { appStore.dispatch(any()) } returns Job()
assertTrue(processorHome.process(testIntent("enable_private_browsing"), navController, out))
verify { appStore.dispatch(AppAction.IntentAction.EnterPrivateBrowsing) }
verify { activity.browsingModeManager.mode = BrowsingMode.Private }
verify { navController.navigate(NavGraphDirections.actionGlobalHome()) }
verify { out wasNot Called }
}
@ -235,7 +228,7 @@ class HomeDeepLinkIntentProcessorTest {
@Test
fun `process invalid open deep link`() {
val invalidProcessor = HomeDeepLinkIntentProcessor(activity, mockk())
val invalidProcessor = HomeDeepLinkIntentProcessor(activity)
assertTrue(invalidProcessor.process(testIntent("open"), navController, out))

@ -10,7 +10,6 @@ import io.mockk.Called
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.Job
import mozilla.components.concept.engine.EngineSession
import mozilla.components.service.glean.testing.GleanTestRule
import mozilla.components.support.test.robolectric.testContext
@ -24,9 +23,7 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.onboarding.ReEngagementNotificationWorker
import org.mozilla.fenix.utils.Settings
@ -42,7 +39,7 @@ class ReEngagementIntentProcessorTest {
val navController: NavController = mockk()
val out: Intent = mockk()
val settings: Settings = mockk()
val result = ReEngagementIntentProcessor(mockk(), settings, mockk())
val result = ReEngagementIntentProcessor(mockk(), settings)
.process(Intent(), navController, out)
assertFalse(result)
@ -55,19 +52,19 @@ class ReEngagementIntentProcessorTest {
val navController: NavController = mockk(relaxed = true)
val out: Intent = mockk()
val activity: HomeActivity = mockk(relaxed = true)
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val settings: Settings = mockk(relaxed = true)
val appStore: AppStore = mockk(relaxed = true)
val intent = Intent().apply {
putExtra("org.mozilla.fenix.re-engagement.intent", true)
}
every { activity.applicationContext } returns testContext
every { activity.browsingModeManager } returns browsingModeManager
every { settings.reEngagementNotificationType } returns ReEngagementNotificationWorker.NOTIFICATION_TYPE_A
every { appStore.dispatch(any()) } returns Job()
assertNull(Events.reEngagementNotifTapped.testGetValue())
val result = ReEngagementIntentProcessor(activity, settings, appStore)
val result = ReEngagementIntentProcessor(activity, settings)
.process(intent, navController, out)
assert(result)
@ -86,7 +83,6 @@ class ReEngagementIntentProcessorTest {
historyMetadata = null,
)
}
verify { appStore.dispatch(AppAction.OpenTabInBrowser(BrowsingMode.Private)) }
verify { navController wasNot Called }
verify { out wasNot Called }
}
@ -96,17 +92,19 @@ class ReEngagementIntentProcessorTest {
val navController: NavController = mockk(relaxed = true)
val out: Intent = mockk()
val activity: HomeActivity = mockk(relaxed = true)
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val settings: Settings = mockk(relaxed = true)
val intent = Intent().apply {
putExtra("org.mozilla.fenix.re-engagement.intent", true)
}
every { activity.applicationContext } returns testContext
every { activity.browsingModeManager } returns browsingModeManager
every { settings.reEngagementNotificationType } returns ReEngagementNotificationWorker.NOTIFICATION_TYPE_B
assertNull(Events.reEngagementNotifTapped.testGetValue())
val result = ReEngagementIntentProcessor(activity, settings, mockk())
val result = ReEngagementIntentProcessor(activity, settings)
.process(intent, navController, out)
assert(result)

@ -42,10 +42,7 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.Services
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.ext.components
@ -68,8 +65,6 @@ class BookmarkControllerTest {
private val navBackStackEntry: NavBackStackEntry = mockk(relaxed = true)
private val navDestination: NavDestination = mockk(relaxed = true)
private lateinit var appStore: AppStore
private val item =
BookmarkNode(BookmarkNodeType.ITEM, "456", "123", 0u, "Mozilla", "http://mozilla.org", 0, null)
private val subfolder =
@ -127,7 +122,6 @@ class BookmarkControllerTest {
every { bookmarkStore.dispatch(any()) } returns mockk()
every { sharedViewModel.selectedFolder = any() } just runs
every { tabsUseCases.addTab } returns addNewTabUseCase
appStore = AppStore()
}
@Test
@ -176,8 +170,8 @@ class BookmarkControllerTest {
@Test
fun `WHEN handleBookmarkTapped is called with private browsing THEN load the bookmark in new tab`() {
every { homeActivity.browsingModeManager.mode } returns BrowsingMode.Private
val flags = EngineSession.LoadUrlFlags.select(EngineSession.LoadUrlFlags.ALLOW_JAVASCRIPT_URL)
appStore = AppStore(AppState(mode = BrowsingMode.Private))
createController().handleBookmarkTapped(item)
@ -191,6 +185,22 @@ class BookmarkControllerTest {
}
}
@Test
fun `handleBookmarkTapped should respect browsing mode`() {
// if in normal mode, should be in normal mode
every { homeActivity.browsingModeManager.mode } returns BrowsingMode.Normal
val controller = createController()
controller.handleBookmarkTapped(item)
assertEquals(BrowsingMode.Normal, homeActivity.browsingModeManager.mode)
// if in private mode, should be in private mode
every { homeActivity.browsingModeManager.mode } returns BrowsingMode.Private
controller.handleBookmarkTapped(item)
assertEquals(BrowsingMode.Private, homeActivity.browsingModeManager.mode)
}
@Test
fun `handleBookmarkExpand should refresh and change the active bookmark node`() = runTestOnMain {
var loadBookmarkNodeInvoked = false
@ -343,7 +353,7 @@ class BookmarkControllerTest {
assertNotNull(openedToPrivateTabsPage)
assertFalse(openedToPrivateTabsPage!!)
verifyOrder {
appStore.dispatch(AppAction.ModeChange(BrowsingMode.Normal))
homeActivity.browsingModeManager.mode = BrowsingMode.Normal
addNewTabUseCase.invoke(item.url!!, private = false)
}
}
@ -363,7 +373,7 @@ class BookmarkControllerTest {
assertNotNull(openedToPrivateTabsPage)
assertTrue(openedToPrivateTabsPage!!)
verifyOrder {
appStore.dispatch(AppAction.ModeChange(BrowsingMode.Private))
homeActivity.browsingModeManager.mode = BrowsingMode.Private
addNewTabUseCase.invoke(item.url!!, private = true)
}
}
@ -402,7 +412,7 @@ class BookmarkControllerTest {
addNewTabUseCase.invoke(item.url!!, private = false)
addNewTabUseCase.invoke(item.url!!, private = false)
addNewTabUseCase.invoke(childItem.url!!, private = false)
appStore.dispatch(AppAction.ModeChange(BrowsingMode.Normal))
homeActivity.browsingModeManager.mode = BrowsingMode.Normal
}
}
@ -440,7 +450,7 @@ class BookmarkControllerTest {
addNewTabUseCase.invoke(item.url!!, private = true)
addNewTabUseCase.invoke(item.url!!, private = true)
addNewTabUseCase.invoke(childItem.url!!, private = true)
appStore.dispatch(AppAction.ModeChange(BrowsingMode.Private))
homeActivity.browsingModeManager.mode = BrowsingMode.Private
}
}
@ -541,7 +551,6 @@ class BookmarkControllerTest {
clipboardManager = clipboardManager,
scope = scope,
store = bookmarkStore,
appStore = appStore,
sharedViewModel = sharedViewModel,
tabsUseCases = tabsUseCases,
loadBookmarkNode = loadBookmarkNode,

@ -28,10 +28,12 @@ class DownloadControllerTest {
private val store: DownloadFragmentStore = mockk(relaxed = true)
private val state: DownloadFragmentState = mockk(relaxed = true)
private val openToFileManager: (DownloadItem) -> Unit = { item ->
private val openToFileManager: (DownloadItem, BrowsingMode?) -> Unit = { item, mode ->
openToFileManagerCapturedItem = item
openToFileManagerCapturedMode = mode
}
private var openToFileManagerCapturedItem: DownloadItem? = null
private var openToFileManagerCapturedMode: BrowsingMode? = null
private val invalidateOptionsMenu: () -> Unit = { wasInvalidateOptionsMenuCalled = true }
private var wasInvalidateOptionsMenuCalled = false
@ -56,13 +58,15 @@ class DownloadControllerTest {
controller.handleOpen(downloadItem)
assertEquals(downloadItem, openToFileManagerCapturedItem)
assertEquals(null, openToFileManagerCapturedMode)
}
@Test
fun onOpenItem() {
controller.handleOpen(downloadItem)
fun onOpenItemInNormalMode() {
controller.handleOpen(downloadItem, BrowsingMode.Normal)
assertEquals(downloadItem, openToFileManagerCapturedItem)
assertEquals(BrowsingMode.Normal, openToFileManagerCapturedMode)
}
@Test

@ -46,9 +46,7 @@ import org.mozilla.fenix.GleanMetrics.UnifiedSearch
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.Core
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.metrics.MetricsUtils
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.search.SearchDialogFragmentDirections.Companion.actionGlobalAddonsManagementFragment
@ -76,7 +74,6 @@ class SearchDialogControllerTest {
private lateinit var middleware: CaptureActionsMiddleware<BrowserState, BrowserAction>
private lateinit var browserStore: BrowserStore
private lateinit var appStore: AppStore
@get:Rule
val gleanTestRule = GleanTestRule(testContext)
@ -89,7 +86,6 @@ class SearchDialogControllerTest {
browserStore = BrowserStore(
middleware = listOf(middleware),
)
appStore = AppStore()
every { store.state.tabId } returns "test-tab-id"
every { store.state.searchEngineSource.searchEngine } returns searchEngine
every { searchEngine.type } returns SearchEngine.Type.BUNDLED
@ -437,7 +433,7 @@ class SearchDialogControllerTest {
fun handleSearchShortcutEngineSelected() {
val searchEngine: SearchEngine = mockk(relaxed = true)
val browsingMode = BrowsingMode.Private
appStore = AppStore(AppState(mode = browsingMode))
every { activity.browsingModeManager.mode } returns browsingMode
var focusToolbarInvoked = false
createController(
@ -634,7 +630,6 @@ class SearchDialogControllerTest {
return SearchDialogController(
activity = activity,
store = browserStore,
appStore = appStore,
tabsUseCases = TabsUseCases(browserStore),
fragmentStore = store,
navController = navController,

@ -29,9 +29,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -39,13 +36,11 @@ import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
internal class SearchDialogFragmentTest {
private val navController: NavController = mockk()
private val fragment = SearchDialogFragment()
private var appStore: AppStore = AppStore()
@Before
fun setup() {
mockkStatic("androidx.navigation.fragment.FragmentKt")
every { any<Fragment>().findNavController() } returns navController
every { testContext.components.appStore } returns appStore
}
@After
@ -161,18 +156,17 @@ internal class SearchDialogFragmentTest {
@Test
fun `GIVEN app is in private mode WHEN search dialog is created THEN the dialog is secure`() {
appStore = AppStore(AppState(mode = BrowsingMode.Private))
val activity: HomeActivity = mockk(relaxed = true)
val fragment = spyk(SearchDialogFragment())
val layoutParams = LayoutParams()
layoutParams.flags = LayoutParams.FLAG_SECURE
every { activity.browsingModeManager.mode.isPrivate } returns true
every { activity.window } returns mockk(relaxed = true) {
every { attributes } returns LayoutParams().apply { flags = LayoutParams.FLAG_SECURE }
}
every { fragment.requireActivity() } returns activity
every { fragment.requireContext() } returns testContext
every { testContext.components.appStore } returns appStore
val dialog = fragment.onCreateDialog(null)
@ -182,11 +176,11 @@ internal class SearchDialogFragmentTest {
@Test
fun `GIVEN app is in normal mode WHEN search dialog is created THEN the dialog is not secure`() {
val activity: HomeActivity = mockk(relaxed = true)
appStore = AppStore(AppState(mode = BrowsingMode.Normal))
val fragment = spyk(SearchDialogFragment())
val layoutParams = LayoutParams()
layoutParams.flags = LayoutParams.FLAG_SECURE
every { activity.browsingModeManager.mode.isPrivate } returns false
every { activity.window } returns mockk(relaxed = true) {
every { attributes } returns LayoutParams().apply { flags = LayoutParams.FLAG_SECURE }
}

@ -27,10 +27,10 @@ import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.metrics.MetricsUtils
import org.mozilla.fenix.utils.Settings
@ -38,6 +38,8 @@ class SearchFragmentStoreTest {
@MockK private lateinit var searchEngine: SearchEngine
@MockK private lateinit var activity: HomeActivity
@MockK(relaxed = true)
private lateinit var components: Components
@ -47,12 +49,15 @@ class SearchFragmentStoreTest {
@Before
fun setup() {
MockKAnnotations.init(this)
every { activity.browsingModeManager } returns object : BrowsingModeManager {
override var mode: BrowsingMode = BrowsingMode.Normal
}
every { components.settings } returns settings
every { components.appStore } returns AppStore()
}
@Test
fun `createInitialSearchFragmentState with no tab in normal browsing mode`() {
activity.browsingModeManager.mode = BrowsingMode.Normal
every { components.core.store.state } returns BrowserState()
every { settings.shouldShowSearchShortcuts } returns true
every { settings.showUnifiedSearchFeature } returns true
@ -95,6 +100,7 @@ class SearchFragmentStoreTest {
assertEquals(
expected,
createInitialSearchFragmentState(
activity,
components,
tabId = null,
pastedText = "pastedText",
@ -104,6 +110,7 @@ class SearchFragmentStoreTest {
assertEquals(
expected.copy(tabId = "tabId"),
createInitialSearchFragmentState(
activity,
components,
tabId = "tabId",
pastedText = "pastedText",
@ -117,8 +124,8 @@ class SearchFragmentStoreTest {
@Test
fun `createInitialSearchFragmentState with no tab in private browsing mode`() {
activity.browsingModeManager.mode = BrowsingMode.Private
every { components.core.store.state } returns BrowserState()
every { components.appStore } returns AppStore(AppState(mode = BrowsingMode.Private))
every { settings.shouldShowSearchShortcuts } returns true
every { settings.showUnifiedSearchFeature } returns true
every { settings.shouldShowHistorySuggestions } returns true
@ -159,6 +166,7 @@ class SearchFragmentStoreTest {
assertEquals(
expected,
createInitialSearchFragmentState(
activity,
components,
tabId = null,
pastedText = "pastedText",
@ -169,6 +177,7 @@ class SearchFragmentStoreTest {
@Test
fun `createInitialSearchFragmentState with tab`() {
activity.browsingModeManager.mode = BrowsingMode.Private
every { components.core.store.state } returns BrowserState(
tabs = listOf(
TabSessionState(
@ -210,6 +219,7 @@ class SearchFragmentStoreTest {
searchAccessPoint = MetricsUtils.Source.SHORTCUT,
),
createInitialSearchFragmentState(
activity,
components,
tabId = "tabId",
pastedText = "",
@ -220,13 +230,14 @@ class SearchFragmentStoreTest {
@Test
fun `GIVEN sponsored and non-sponsored suggestions are enabled and Firefox Suggest is disabled WHEN the initial state is created THEN neither are displayed`() {
every { components.appStore } returns AppStore()
activity.browsingModeManager.mode = BrowsingMode.Normal
every { components.core.store.state } returns BrowserState()
every { settings.enableFxSuggest } returns false
every { settings.showSponsoredSuggestions } returns true
every { settings.showNonSponsoredSuggestions } returns true
val initialState = createInitialSearchFragmentState(
activity,
components,
tabId = null,
pastedText = "pastedText",

@ -38,9 +38,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.Core.Companion
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -51,7 +49,6 @@ import org.mozilla.fenix.utils.Settings
@RunWith(FenixRobolectricTestRunner::class)
class AwesomeBarViewTest {
private var activity: HomeActivity = mockk(relaxed = true)
private var appStore = AppStore()
private lateinit var awesomeBarView: AwesomeBarView
@Before
@ -68,7 +65,6 @@ class AwesomeBarViewTest {
every { any<Activity>().components.core.client } returns mockk()
every { any<Activity>().components.backgroundServices.syncedTabsStorage } returns mockk()
every { any<Activity>().components.core.store.state.search } returns mockk(relaxed = true)
every { any<Activity>().components.appStore } returns appStore
every { any<Activity>().getColorFromAttr(any()) } returns 0
every { AwesomeBarView.Companion.getDrawable(any(), any()) } returns mockk<VectorDrawable>(relaxed = true) {
every { intrinsicWidth } returns 10
@ -773,6 +769,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showSessionSuggestionsForCurrentEngine = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -818,6 +815,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showAllSessionSuggestions = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -836,10 +834,9 @@ class AwesomeBarViewTest {
@Test
fun `GIVEN private browsing mode and needing to show tabs suggestions WHEN configuring providers THEN don't add the tabs provider`() {
val appStore = AppStore(AppState(mode = BrowsingMode.Private))
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
every { any<Activity>().components.appStore } returns appStore
every { activity.browsingModeManager.mode } returns BrowsingMode.Private
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Shortcut(mockk(relaxed = true)),
)
@ -854,6 +851,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showSyncedTabsSuggestionsForCurrentEngine = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -876,6 +874,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showAllSyncedTabsSuggestions = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -921,6 +920,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showBookmarksSuggestionsForCurrentEngine = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -966,6 +966,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showAllBookmarkSuggestions = false,
searchEngineSource = SearchEngineSource.Shortcut(
@ -1000,6 +1001,7 @@ class AwesomeBarViewTest {
val settings: Settings = mockk(relaxed = true)
val url = Uri.parse("https://www.test.com")
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
searchEngineSource = SearchEngineSource.Default(
mockk(relaxed = true) {
@ -1074,6 +1076,7 @@ class AwesomeBarViewTest {
fun `GIVEN a search from the default engine with no suggestions asked WHEN configuring providers THEN add only search engine suggestion provider`() {
val settings: Settings = mockk(relaxed = true)
every { activity.settings() } returns settings
every { activity.browsingModeManager.mode } returns BrowsingMode.Normal
val state = getSearchProviderState(
showHistorySuggestionsForCurrentEngine = false,
showSearchShortcuts = false,

@ -57,11 +57,12 @@ import org.mozilla.fenix.GleanMetrics.TabsTray
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.collections.CollectionsDialog
import org.mozilla.fenix.collections.show
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.appstate.AppState
import org.mozilla.fenix.components.bookmarks.BookmarksUseCase
import org.mozilla.fenix.ext.maxActiveTime
import org.mozilla.fenix.ext.potentialInactiveTabs
@ -79,6 +80,9 @@ class DefaultTabsTrayControllerTest {
@MockK(relaxed = true)
private lateinit var browserStore: BrowserStore
@MockK(relaxed = true)
private lateinit var browsingModeManager: BrowsingModeManager
@MockK(relaxed = true)
private lateinit var navController: NavController
@ -94,7 +98,7 @@ class DefaultTabsTrayControllerTest {
@MockK(relaxed = true)
private lateinit var activity: HomeActivity
private lateinit var appStore: AppStore
private val appStore: AppStore = mockk(relaxed = true)
private val settings: Settings = mockk(relaxed = true)
private val bookmarksUseCase: BookmarksUseCase = mockk(relaxed = true)
@ -113,7 +117,6 @@ class DefaultTabsTrayControllerTest {
@Before
fun setup() {
MockKAnnotations.init(this)
appStore = AppStore()
}
@Test
@ -139,7 +142,6 @@ class DefaultTabsTrayControllerTest {
Double.MAX_VALUE,
)
}
assertEquals(BrowsingMode.Private, appStore.state.mode)
}
@Test
@ -147,7 +149,6 @@ class DefaultTabsTrayControllerTest {
profiler = spyk(profiler) {
every { getProfilerTime() } returns Double.MAX_VALUE
}
appStore = AppStore(AppState(mode = BrowsingMode.Private))
createController().handleNormalTabsFabClick()
@ -941,6 +942,13 @@ class DefaultTabsTrayControllerTest {
tabs = listOf(normalTab, privateTab),
),
)
browsingModeManager = spyk(
DefaultBrowsingModeManager(
_mode = BrowsingMode.Private,
settings = settings,
modeDidChange = mockk(relaxed = true),
),
)
val controller = spyk(createController())
try {
@ -949,13 +957,14 @@ class DefaultTabsTrayControllerTest {
controller.handleTabSelected(privateTab, null)
assertEquals(privateTab.id, browserStore.state.selectedTabId)
assertEquals(true, browsingModeManager.mode.isPrivate)
controller.handleTabDeletion("privateTab")
browserStore.dispatch(TabListAction.SelectTabAction(normalTab.id)).joinBlocking()
controller.handleTabSelected(normalTab, null)
assertEquals(normalTab.id, browserStore.state.selectedTabId)
assertEquals(false, appStore.state.mode.isPrivate)
assertEquals(false, browsingModeManager.mode.isPrivate)
} finally {
unmockkStatic("mozilla.components.browser.state.selector.SelectorsKt")
}
@ -1134,6 +1143,7 @@ class DefaultTabsTrayControllerTest {
tabsTrayStore = trayStore,
browserStore = browserStore,
settings = settings,
browsingModeManager = browsingModeManager,
navController = navController,
navigateToHomeAndDeleteSession = navigateToHomeAndDeleteSession,
profiler = profiler,

@ -11,14 +11,14 @@ import io.mockk.mockk
import io.mockk.verify
import org.junit.Test
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_NORMAL_TABS
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_PRIVATE_TABS
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.POSITION_SYNCED_TABS
class TabLayoutMediatorTest {
private val modeManager: BrowsingModeManager = mockk(relaxed = true)
private val tabsTrayStore: TabsTrayStore = mockk(relaxed = true)
private val appStore: AppStore = mockk(relaxed = true)
private val interactor: TabsTrayInteractor = mockk(relaxed = true)
private val tabLayout: TabLayout = mockk(relaxed = true)
private val tab: TabLayout.Tab = mockk(relaxed = true)
@ -26,10 +26,10 @@ class TabLayoutMediatorTest {
@Test
fun `page to normal tab position when mode is also normal`() {
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, appStore, tabsTrayStore)
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, modeManager, tabsTrayStore)
val mockState: TabsTrayState = mockk()
every { appStore.state } returns mockk { every { mode } returns BrowsingMode.Normal }
every { modeManager.mode }.answers { BrowsingMode.Normal }
every { tabLayout.getTabAt(POSITION_NORMAL_TABS) }.answers { tab }
every { tabsTrayStore.state } returns mockState
every { mockState.selectedPage } returns Page.NormalTabs
@ -43,9 +43,9 @@ class TabLayoutMediatorTest {
@Test
fun `page to private tab position when mode is also private`() {
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, appStore, tabsTrayStore)
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, modeManager, tabsTrayStore)
every { appStore.state } returns mockk { every { mode } returns BrowsingMode.Private }
every { modeManager.mode }.answers { BrowsingMode.Private }
every { tabLayout.getTabAt(POSITION_PRIVATE_TABS) }.answers { tab }
mediator.selectActivePage()
@ -56,10 +56,10 @@ class TabLayoutMediatorTest {
@Test
fun `page to synced tabs when selected page is also synced tabs`() {
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, appStore, tabsTrayStore)
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, modeManager, tabsTrayStore)
val mockState: TabsTrayState = mockk()
every { appStore.state } returns mockk { every { mode } returns BrowsingMode.Normal }
every { modeManager.mode }.answers { BrowsingMode.Normal }
every { tabsTrayStore.state } returns mockState
every { mockState.selectedPage } returns Page.SyncedTabs
@ -70,7 +70,7 @@ class TabLayoutMediatorTest {
@Test
fun `selectTabAtPosition will dispatch the correct TabsTrayStore action`() {
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, appStore, tabsTrayStore)
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, modeManager, tabsTrayStore)
every { tabLayout.getTabAt(POSITION_NORMAL_TABS) }.answers { tab }
every { tabLayout.getTabAt(POSITION_PRIVATE_TABS) }.answers { tab }
@ -91,9 +91,9 @@ class TabLayoutMediatorTest {
@Test
fun `lifecycle methods adds and removes observer`() {
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, appStore, tabsTrayStore)
val mediator = TabLayoutMediator(tabLayout, viewPager, interactor, modeManager, tabsTrayStore)
every { appStore.state } returns mockk { every { mode } returns BrowsingMode.Private }
every { modeManager.mode }.answers { BrowsingMode.Private }
mediator.start()

Loading…
Cancel
Save