commit fa3257dcab38a906a26add9423a22e9155094c76 parent ab0adc092ab30edb788efb407c1f3bbce4243bb0 Author: rmalicdem <rmalicdem@mozilla.com> Date: Mon, 24 Nov 2025 16:11:00 +0000 Bug 1986697 - Show extensions status in the custom tabs menu r=android-reviewers,petru,rpl Differential Revision: https://phabricator.services.mozilla.com/D265889 Diffstat:
12 files changed, 228 insertions(+), 40 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt @@ -72,6 +72,7 @@ import org.mozilla.fenix.automotive.isAndroidAutomotiveAvailable import org.mozilla.fenix.components.appstate.SupportedMenuNotifications import org.mozilla.fenix.components.components import org.mozilla.fenix.components.menu.compose.Addons +import org.mozilla.fenix.components.menu.compose.CustomTabAddons import org.mozilla.fenix.components.menu.compose.CustomTabMenu import org.mozilla.fenix.components.menu.compose.MainMenu import org.mozilla.fenix.components.menu.compose.MenuCFRState @@ -352,7 +353,8 @@ class MenuDialogFragment : BottomSheetDialogFragment() { handlebarContentDescription = handlebarContentDescription, isMenuDragBarDark = !settings.shouldUseBottomToolbar && !settings.shouldUseExpandedToolbar && - (isExtensionsExpanded || isMoreMenuExpanded), + (isExtensionsExpanded || isMoreMenuExpanded) && + args.accesspoint == MenuAccessPoint.Browser, cornerShape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp), handleColor = FirefoxTheme.colors.borderInverted.copy(0.4f), handleCornerRadius = CornerRadius(100f, 100f), @@ -400,6 +402,7 @@ class MenuDialogFragment : BottomSheetDialogFragment() { webExtensionsMenuBinding.set( feature = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = args.customTabSessionId, menuStore = store, iconSize = 24.dpToPx(requireContext().resources.displayMetrics), onDismiss = { this@MenuDialogFragment.dismiss() }, @@ -478,6 +481,13 @@ class MenuDialogFragment : BottomSheetDialogFragment() { var shouldShowMenuBanner by remember { mutableStateOf(settings.shouldShowMenuBanner) } + val extensionsMenuItemDescription = getExtensionsMenuItemDescription( + isExtensionsProcessDisabled = isExtensionsProcessDisabled, + allWebExtensionsDisabled = allWebExtensionsDisabled, + availableAddons = availableAddons, + browserWebExtensionMenuItems = browserWebExtensionMenuItem, + ) + BackHandler { this@MenuDialogFragment.dismissAllowingStateLoss() } @@ -536,13 +546,6 @@ class MenuDialogFragment : BottomSheetDialogFragment() { null } - val extensionsMenuItemDescription = getExtensionsMenuItemDescription( - isExtensionsProcessDisabled = isExtensionsProcessDisabled, - allWebExtensionsDisabled = allWebExtensionsDisabled, - availableAddons = availableAddons, - browserWebExtensionMenuItems = browserWebExtensionMenuItem, - ) - val isDownloadHighlighted by appStore.observeAsState( initialValue = false, ) { state -> @@ -772,6 +775,13 @@ class MenuDialogFragment : BottomSheetDialogFragment() { isPdf = customTab?.content?.isPdf == true, isDesktopMode = isDesktopMode, isSandboxCustomTab = args.isSandboxCustomTab, + isPrivate = isPrivate, + isExtensionsExpanded = isExtensionsExpanded, + isExtensionsProcessDisabled = isExtensionsProcessDisabled, + isAllWebExtensionsDisabled = allWebExtensionsDisabled, + shouldShowExtensionsMenu = settings.shouldShowCustomTabExtensions, + webExtensionMenuCount = webExtensionsCount, + extensionsMenuDescription = extensionsMenuItemDescription, customTabMenuItems = customTab?.config?.menuItems, onCustomMenuItemClick = { intent: PendingIntent -> store.dispatch( @@ -809,6 +819,24 @@ class MenuDialogFragment : BottomSheetDialogFragment() { onShareButtonClick = { store.dispatch(MenuAction.Navigate.Share) }, + onExtensionsMenuClick = { + if (!allWebExtensionsDisabled && !isExtensionsProcessDisabled) { + isExtensionsExpanded = !isExtensionsExpanded + } + }, + extensionSubmenu = { + CustomTabAddons( + availableAddons = availableAddons, + webExtensionMenuItems = browserWebExtensionMenuItem, + onWebExtensionMenuItemClick = { + Events.browserMenuAction.record( + Events.BrowserMenuActionExtra( + item = "web_extension_browser_action_clicked", + ), + ) + }, + ) + }, ) } } @@ -824,6 +852,9 @@ class MenuDialogFragment : BottomSheetDialogFragment() { availableAddons: List<Addon>, browserWebExtensionMenuItems: List<WebExtensionMenuItem>, ): String? { + val isBrowserOrExternal = args.accesspoint == MenuAccessPoint.Browser || + args.accesspoint == MenuAccessPoint.External + return when { args.accesspoint == MenuAccessPoint.Home -> null @@ -831,19 +862,15 @@ class MenuDialogFragment : BottomSheetDialogFragment() { requireContext().getString(R.string.browser_menu_extensions_disabled_description) } - args.accesspoint == MenuAccessPoint.Browser && browserWebExtensionMenuItems.isNotEmpty() -> { - browserWebExtensionMenuItems.joinToString( - separator = ", ", - ) { - it.label - } + isBrowserOrExternal && browserWebExtensionMenuItems.isNotEmpty() -> { + browserWebExtensionMenuItems.joinToString(separator = ", ") { it.label } } allWebExtensionsDisabled -> { requireContext().getString(R.string.browser_menu_no_extensions_installed_description) } - args.accesspoint == MenuAccessPoint.Browser && availableAddons.isEmpty() -> { + isBrowserOrExternal && availableAddons.isEmpty() -> { requireContext().getString(R.string.browser_menu_try_a_recommended_extension_description) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/WebExtensionsMenuBinding.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/WebExtensionsMenuBinding.kt @@ -8,8 +8,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.mapNotNull -import mozilla.components.browser.state.selector.selectedTab +import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.WebExtensionState import mozilla.components.browser.state.store.BrowserStore @@ -27,12 +28,14 @@ import org.mozilla.fenix.components.menu.store.WebExtensionMenuItem * and [TabSessionState.extensionState]. * * @param browserStore Used to listen for changes to [WebExtensionState]. + * @param customTabId The ID of the custom tab to observe, or null to observe the selected tab. * @param menuStore The [Store] for holding the [MenuState] and applying [MenuAction]s. * @param iconSize for [WebExtensionMenuItem]. * @param onDismiss Callback invoked to dismiss the menu dialog. */ class WebExtensionsMenuBinding( browserStore: BrowserStore, + private val customTabId: String?, private val menuStore: MenuStore, private val iconSize: Int, private val onDismiss: () -> Unit, @@ -46,7 +49,7 @@ class WebExtensionsMenuBinding( } // Session level flows - val sessionFlow = flow.mapNotNull { state -> state.selectedTab } + val sessionFlow = flow.mapNotNull { state -> state.findCustomTabOrSelectedTab(customTabId) } .distinctUntilChangedBy { it.extensionState } @@ -154,6 +157,6 @@ class WebExtensionsMenuBinding( * @property browserState The browser or global state. */ private data class WebExtensionsFlowState( - val sessionState: TabSessionState, + val sessionState: SessionState, val browserState: BrowserState, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/CustomTabMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/CustomTabMenu.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -33,9 +34,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import mozilla.components.browser.state.state.CustomTabMenuItem +import mozilla.components.feature.addons.Addon import org.mozilla.fenix.R +import org.mozilla.fenix.components.menu.MenuAccessPoint import org.mozilla.fenix.components.menu.MenuDialogTestTag.DESKTOP_SITE_OFF import org.mozilla.fenix.components.menu.MenuDialogTestTag.DESKTOP_SITE_ON +import org.mozilla.fenix.components.menu.store.WebExtensionMenuItem import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme import mozilla.components.ui.icons.R as iconsR @@ -50,6 +54,13 @@ import mozilla.components.ui.icons.R as iconsR * @param isPdf Whether or not the current custom tab is a PDF. * @param isDesktopMode Whether or not the current site is in desktop mode. * @param isSandboxCustomTab Whether or not the current custom tab is sandboxed. + * @param isPrivate Whether or not the current custom tab is in a private browsing session. + * @param isExtensionsExpanded Whether or not the extensions submenu is expanded. + * @param isExtensionsProcessDisabled Whether or not the extensions process is disabled due to extension errors. + * @param isAllWebExtensionsDisabled Whether or not all web extensions are disabled. + * @param shouldShowExtensionsMenu Whether or not the extensions menu item should be shown. + * @param webExtensionMenuCount The number of web extensions. + * @param extensionsMenuDescription The description to be shown below the extensions menu item. * @param customTabMenuItems Additional [CustomTabMenuItem]s to be displayed to the custom tab menu. * @param onCustomMenuItemClick Invoked when the user clicks on [CustomTabMenuItem]s. * @param scrollState The [ScrollState] used for vertical scrolling. @@ -62,6 +73,8 @@ import mozilla.components.ui.icons.R as iconsR * @param onRefreshButtonClick Invoked when the user clicks on the refresh button. * @param onStopButtonClick Invoked when the user clicks on the stop button. * @param onShareButtonClick Invoked when the user clicks on the share button. + * @param onExtensionsMenuClick Invoked when the user clicks on the extensions menu item. + * @param extensionSubmenu The submenu content to be shown when the extensions menu item is expanded */ @Suppress("LongParameterList", "LongMethod", "CyclomaticComplexMethod", "CognitiveComplexMethod") @Composable @@ -73,6 +86,13 @@ internal fun CustomTabMenu( isPdf: Boolean, isDesktopMode: Boolean, isSandboxCustomTab: Boolean, + isPrivate: Boolean, + isExtensionsExpanded: Boolean, + isExtensionsProcessDisabled: Boolean, + isAllWebExtensionsDisabled: Boolean, + shouldShowExtensionsMenu: Boolean, + webExtensionMenuCount: Int, + extensionsMenuDescription: String?, customTabMenuItems: List<CustomTabMenuItem>?, onCustomMenuItemClick: (PendingIntent) -> Unit, scrollState: ScrollState, @@ -84,6 +104,8 @@ internal fun CustomTabMenu( onRefreshButtonClick: (longPress: Boolean) -> Unit, onStopButtonClick: () -> Unit, onShareButtonClick: () -> Unit, + onExtensionsMenuClick: () -> Unit, + extensionSubmenu: @Composable ColumnScope.() -> Unit, ) { MenuFrame( contentModifier = Modifier @@ -199,6 +221,19 @@ internal fun CustomTabMenu( badgeBackgroundColor = badgeBackgroundColor, ) } + + if (shouldShowExtensionsMenu) { + ExtensionsMenuItem( + isExtensionsProcessDisabled = isExtensionsProcessDisabled, + isExtensionsExpanded = isExtensionsExpanded, + isPrivate = isPrivate, + webExtensionMenuCount = webExtensionMenuCount, + allWebExtensionsDisabled = isAllWebExtensionsDisabled, + onExtensionsMenuClick = onExtensionsMenuClick, + extensionSubmenu = extensionSubmenu, + extensionsMenuItemDescription = extensionsMenuDescription, + ) + } } if (!customTabMenuItems.isNullOrEmpty()) { @@ -220,6 +255,27 @@ internal fun CustomTabMenu( } } +@Composable +internal fun CustomTabAddons( + availableAddons: List<Addon>, + webExtensionMenuItems: List<WebExtensionMenuItem>, + onWebExtensionMenuItemClick: () -> Unit, +) { + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { + if (webExtensionMenuItems.isNotEmpty()) { + WebExtensionMenuItems( + accessPoint = MenuAccessPoint.External, + webExtensionMenuItems = webExtensionMenuItems, + onWebExtensionMenuItemClick = onWebExtensionMenuItemClick, + availableAddons = availableAddons, + onSettingsClick = {}, + ) + } + } +} + /** * A menu item that shows the "Powered by Firefox" text and logo. * @@ -269,6 +325,13 @@ private fun CustomTabMenuPreview() { isPdf = false, isDesktopMode = false, isSandboxCustomTab = false, + isPrivate = false, + isExtensionsExpanded = false, + isExtensionsProcessDisabled = false, + isAllWebExtensionsDisabled = false, + shouldShowExtensionsMenu = true, + webExtensionMenuCount = 2, + extensionsMenuDescription = "Extension 1, Extension 2", customTabMenuItems = null, onCustomMenuItemClick = { _: PendingIntent -> }, scrollState = rememberScrollState(), @@ -280,6 +343,8 @@ private fun CustomTabMenuPreview() { onRefreshButtonClick = {}, onStopButtonClick = {}, onShareButtonClick = {}, + onExtensionsMenuClick = {}, + extensionSubmenu = {}, ) } } @@ -302,6 +367,13 @@ private fun CustomTabMenuPrivatePreview() { isPdf = true, isDesktopMode = false, isSandboxCustomTab = false, + isPrivate = true, + isExtensionsExpanded = true, + isExtensionsProcessDisabled = true, + isAllWebExtensionsDisabled = true, + shouldShowExtensionsMenu = true, + webExtensionMenuCount = 0, + extensionsMenuDescription = "Temporarily disabled", customTabMenuItems = null, onCustomMenuItemClick = { _: PendingIntent -> }, scrollState = rememberScrollState(), @@ -313,6 +385,8 @@ private fun CustomTabMenuPrivatePreview() { onRefreshButtonClick = {}, onStopButtonClick = {}, onShareButtonClick = {}, + onExtensionsMenuClick = {}, + extensionSubmenu = {}, ) } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/MainMenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/MainMenu.kt @@ -67,6 +67,7 @@ import mozilla.components.feature.addons.ui.summary import mozilla.components.service.fxa.manager.AccountState import mozilla.components.service.fxa.manager.AccountState.AuthenticationProblem import mozilla.components.service.fxa.store.Account +import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.R import org.mozilla.fenix.components.menu.MenuAccessPoint import org.mozilla.fenix.components.menu.MenuDialogTestTag.DESKTOP_SITE_OFF @@ -338,7 +339,7 @@ fun MainMenu( @Suppress("LongParameterList", "LongMethod", "CognitiveComplexMethod") @Composable -private fun ExtensionsMenuItem( +internal fun ExtensionsMenuItem( isExtensionsProcessDisabled: Boolean, isExtensionsExpanded: Boolean, isPrivate: Boolean, @@ -789,6 +790,7 @@ internal fun Addons( ) } else if (accessPoint == MenuAccessPoint.Browser && webExtensionMenuItems.isNotEmpty()) { WebExtensionMenuItems( + accessPoint = accessPoint, webExtensionMenuItems = webExtensionMenuItems, onWebExtensionMenuItemClick = onWebExtensionMenuItemClick, availableAddons = availableAddons, @@ -859,7 +861,8 @@ private fun AddonsMenuItems( } @Composable -private fun WebExtensionMenuItems( +internal fun WebExtensionMenuItems( + accessPoint: MenuAccessPoint, webExtensionMenuItems: List<WebExtensionMenuItem>, onWebExtensionMenuItemClick: () -> Unit, availableAddons: List<Addon> = emptyList(), @@ -892,14 +895,23 @@ private fun WebExtensionMenuItems( enabled = webExtensionMenuItem.enabled, badgeText = webExtensionMenuItem.badgeText, onClick = { - onWebExtensionMenuItemClick() - webExtensionMenuItem.onClick() - }, - onSettingsClick = { - if (addon != null) { - onSettingsClick(addon) + if (accessPoint != MenuAccessPoint.External) { + onWebExtensionMenuItemClick() + webExtensionMenuItem.onClick() + } else { + // TODO(Bug 1959344): CustomTab should be visible to add-ons through the tabs API + // and it should be detected as active tab while in foreground. + Logger.error( + message = "WebExtensionsMenuItem does not does not support onClick in CustomTab mode", + throwable = NotImplementedError(), + ) } }, + onSettingsClick = if (accessPoint != MenuAccessPoint.External) { + { addon?.let { onSettingsClick(addon) } } + } else { + null + }, ) } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/MenuItem.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/MenuItem.kt @@ -268,17 +268,19 @@ internal fun WebExtensionMenuItem( ) } - VerticalDivider() - - IconButton( - modifier = Modifier.size(24.dp), - onClick = onSettingsClick ?: {}, - ) { - Icon( - painter = painterResource(iconsR.drawable.mozac_ic_settings_24), - tint = MaterialTheme.colorScheme.onSurface, - contentDescription = null, - ) + if (onSettingsClick != null) { + VerticalDivider() + + IconButton( + modifier = Modifier.size(24.dp), + onClick = onSettingsClick, + ) { + Icon( + painter = painterResource(iconsR.drawable.mozac_ic_settings_24), + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = null, + ) + } } } }, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/store/MenuState.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/store/MenuState.kt @@ -89,7 +89,7 @@ data class ExtensionMenuState( val webExtensionsCount: Int get() { return when (accesspoint) { - MenuAccessPoint.Browser -> { + MenuAccessPoint.Browser, MenuAccessPoint.External -> { browserWebExtensionMenuItem.size } MenuAccessPoint.Home -> { @@ -105,11 +105,11 @@ data class ExtensionMenuState( val allWebExtensionsDisabled: Boolean get() { return ( - recommendedAddons.isEmpty() && + (recommendedAddons.isEmpty() || accesspoint == MenuAccessPoint.External) && availableAddons.isEmpty() && browserWebExtensionMenuItem.isEmpty() ) || ( - accesspoint == MenuAccessPoint.Browser && + (accesspoint == MenuAccessPoint.Browser || accesspoint == MenuAccessPoint.External) && browserWebExtensionMenuItem.isEmpty() && availableAddons.isNotEmpty() ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt @@ -95,6 +95,21 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { context.settings().shouldShowToolbarCustomization = false } } + requirePreference<SwitchPreference>(R.string.pref_key_should_show_custom_tab_extensions).apply { + val shouldEnableCustomTabExtensions = newOption || context.settings().enableMenuRedesign + isEnabled = shouldEnableCustomTabExtensions + when (shouldEnableCustomTabExtensions) { + true -> { + summary = null + } + + false -> { + isChecked = false + summary = getString(R.string.preferences_debug_settings_custom_tab_extensions_summary) + context.settings().shouldShowCustomTabExtensions = false + } + } + } } true } @@ -160,6 +175,38 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { requirePreference<SwitchPreference>(R.string.pref_key_enable_menu_redesign).apply { isVisible = Config.channel.isNightlyOrDebug isChecked = context.settings().enableMenuRedesign + onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + (newValue as? Boolean)?.let { newOption -> + context.settings().enableMenuRedesign = newOption + requirePreference<SwitchPreference>(R.string.pref_key_should_show_custom_tab_extensions).apply { + val shouldEnableCustomTabExtensions = newOption || context.settings().shouldUseComposableToolbar + isEnabled = shouldEnableCustomTabExtensions + when (shouldEnableCustomTabExtensions) { + true -> { + summary = null + } + + false -> { + isChecked = false + summary = getString(R.string.preferences_debug_settings_custom_tab_extensions_summary) + context.settings().shouldShowCustomTabExtensions = false + } + } + } + } + true + } + } + + requirePreference<SwitchPreference>(R.string.pref_key_should_show_custom_tab_extensions).apply { + isVisible = Config.channel.isDebug + isChecked = context.settings().shouldShowCustomTabExtensions + val newOption = context.settings().enableMenuRedesign || context.settings().shouldUseComposableToolbar + isEnabled = newOption + summary = when (newOption) { + true -> null + false -> getString(R.string.preferences_debug_settings_custom_tab_extensions_summary) + } onPreferenceChangeListener = SharedPreferenceUpdater() } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -2274,6 +2274,14 @@ class Settings( ) /** + * Indicates if the extensions status should be shown in the menu opened for custom tabs. + */ + var shouldShowCustomTabExtensions by booleanPreference( + key = appContext.getPreferenceKey(R.string.pref_key_should_show_custom_tab_extensions), + default = false, + ) + + /** * Indicates if the Homepage as a New Tab is enabled. */ var enableHomepageAsNewTab by lazyFeatureFlagPreference( diff --git a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml @@ -435,6 +435,7 @@ <string name="pref_key_custom_sponsored_stories_city" translatable="false">pref_key_custom_sponsored_stories_city</string> <string name="pref_key_enable_homepage_searchbar" translatable="false">pref_key_enable_homepage_searchbar</string> <string name="pref_key_enable_menu_redesign" translatable="false">pref_key_enable_menu_redesign</string> + <string name="pref_key_should_show_custom_tab_extensions" translatable="false">pref_key_should_show_custom_tab_extensions</string> <string name="pref_key_enable_homepage_as_new_tab" translatable="false">pref_key_enable_homepage_as_new_tab</string> <string name="pref_key_enable_discover_more_stories" translatable="false">pref_key_enable_discover_more_stories</string> <string name="pref_key_enable_mozilla_ads_client" translatable="false">pref_key_enable_mozilla_ads_client</string> diff --git a/mobile/android/fenix/app/src/main/res/values/static_strings.xml b/mobile/android/fenix/app/src/main/res/values/static_strings.xml @@ -79,6 +79,10 @@ <string name="preferences_debug_settings_discover_more_stories" translatable="false">Enable Discover More Stories</string> <!-- Label for enabling the menu redesign --> <string name="preferences_debug_settings_menu_redesign" translatable="false">Enable Menu Redesign</string> + <!-- Label for enabling the custom tab extension --> + <string name="preferences_debug_settings_custom_tab_extensions" translatable="false">Enable Custom Tab Extension List</string> + <!-- Label for a longer description of the custom tab extensions depending on the menu redesign or composable toolbar feature --> + <string name="preferences_debug_settings_custom_tab_extensions_summary" translatable="false">This needs the Menu Redesign or Composable Toolbar feature enabled</string> <!-- Label for enabling Firefox Suggest --> <string name="preferences_debug_settings_fxsuggest" translatable="false">Enable Firefox Suggest</string> <!-- Label for enabling the composable toolbar --> diff --git a/mobile/android/fenix/app/src/main/res/xml/secret_settings_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/secret_settings_preferences.xml @@ -52,6 +52,11 @@ app:iconSpaceReserved="false" /> <SwitchPreference android:defaultValue="false" + android:key="@string/pref_key_should_show_custom_tab_extensions" + android:title="@string/preferences_debug_settings_custom_tab_extensions" + app:iconSpaceReserved="false" /> + <SwitchPreference + android:defaultValue="false" android:key="@string/pref_key_enable_composable_toolbar" android:title="@string/preferences_debug_settings_composable_toolbar" app:iconSpaceReserved="false" /> diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/WebExtensionsMenuBindingTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/WebExtensionsMenuBindingTest.kt @@ -82,6 +82,7 @@ class WebExtensionsMenuBindingTest { val binding = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = null, menuStore = menuStore, iconSize = 24.dpToPx(testContext.resources.displayMetrics), onDismiss = {}, @@ -130,6 +131,7 @@ class WebExtensionsMenuBindingTest { val binding = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = null, menuStore = menuStore, iconSize = 24.dpToPx(testContext.resources.displayMetrics), onDismiss = {}, @@ -178,6 +180,7 @@ class WebExtensionsMenuBindingTest { val binding = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = null, menuStore = menuStore, iconSize = 24.dpToPx(testContext.resources.displayMetrics), onDismiss = {}, @@ -234,6 +237,7 @@ class WebExtensionsMenuBindingTest { val binding = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = null, menuStore = menuStore, iconSize = 24.dpToPx(testContext.resources.displayMetrics), onDismiss = {}, @@ -286,6 +290,7 @@ class WebExtensionsMenuBindingTest { val binding = WebExtensionsMenuBinding( browserStore = browserStore, + customTabId = null, menuStore = menuStore, iconSize = 24.dpToPx(testContext.resources.displayMetrics), onDismiss = {},