tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 5e7833fdea31106939bf8f832f8606af5c3945ab
parent 26db74bf911e80ea02ef30365d3438fc98aa090a
Author: John Oberhauser <j.git-global@obez.io>
Date:   Tue, 21 Oct 2025 14:15:20 +0000

Bug 1993323: Adding nimbus configurations for the default browser prompt r=android-reviewers,gmalekpour,twhite

Differential Revision: https://phabricator.services.mozilla.com/D268031

Diffstat:
Mmobile/android/fenix/app/nimbus.fml.yaml | 20++++++++++++++++++++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt | 2+-
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt | 43++++++++++++++++++++++---------------------
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 109 insertions(+), 27 deletions(-)

diff --git a/mobile/android/fenix/app/nimbus.fml.yaml b/mobile/android/fenix/app/nimbus.fml.yaml @@ -1037,6 +1037,26 @@ features: type: Boolean default: false + default-browser-prompt: + description: Feature that controls when the default browser prompt is shown. + variables: + enabled: + description: Whether or not to enable the default browser prompt. + type: Boolean + default: true + daysBetweenPrompts: + description: The minimum number of days between showing the prompt. + type: Option<Int> + default: 14 + maxPromptsShown: + description: The maximum number of times the prompt can shown to the user. + type: Option<Int> + default: 3 + coldStartsBetweenPrompts: + description: The minimum number of cold starts between showing the prompt. + type: Option<Int> + default: 4 + types: objects: GleanServerKnobsConfiguration: diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -605,7 +605,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { @VisibleForTesting internal fun maybeShowSetAsDefaultBrowserPrompt( - shouldShowSetAsDefaultPrompt: Boolean = settings().shouldShowSetAsDefaultPrompt, + shouldShowSetAsDefaultPrompt: Boolean = settings().shouldShowSetAsDefaultPrompt(), isDefaultBrowser: Boolean = BrowsersCache.all(applicationContext).isDefaultBrowser, isTheCorrectBuildVersion: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q, ) { 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 @@ -55,6 +55,7 @@ import org.mozilla.fenix.ext.pixelSizeFor import org.mozilla.fenix.home.pocket.ContentRecommendationsFeatureHelper import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_MAX_COUNT import org.mozilla.fenix.nimbus.CookieBannersSection +import org.mozilla.fenix.nimbus.DefaultBrowserPrompt import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.nimbus.HomeScreenSection import org.mozilla.fenix.nimbus.Mr2022Section @@ -112,21 +113,6 @@ class Settings(private val appContext: Context) : PreferencesHolder { @VisibleForTesting internal var searchGroupMinimumSites: Int = 2 - /** - * Minimum number of days between Set as default Browser prompt displays in home page. - */ - const val DAYS_BETWEEN_DEFAULT_BROWSER_PROMPTS: Int = 14 - - /** - * Maximum number of times the Set as default Browser prompt from home page can be displayed to the user. - */ - const val MAX_NUMBER_OF_DEFAULT_BROWSER_PROMPTS: Int = 3 - - /** - * Number of app cold starts before displaying the Set as default Browser prompt from home page. - */ - const val APP_COLD_STARTS_TO_SHOW_DEFAULT_PROMPT: Int = 4 - private fun Action.toInt() = when (this) { Action.BLOCKED -> BLOCKED_INT Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT @@ -2560,12 +2546,27 @@ class Settings(private val appContext: Context) : PreferencesHolder { /** * Indicates if the Set as default Browser prompt should be displayed to the user. */ - val shouldShowSetAsDefaultPrompt: Boolean - get() = - (System.currentTimeMillis() - lastSetAsDefaultPromptShownTimeInMillis) > - DAYS_BETWEEN_DEFAULT_BROWSER_PROMPTS * ONE_DAY_MS && - numberOfSetAsDefaultPromptShownTimes < MAX_NUMBER_OF_DEFAULT_BROWSER_PROMPTS && - coldStartsBetweenSetAsDefaultPrompts >= APP_COLD_STARTS_TO_SHOW_DEFAULT_PROMPT + fun shouldShowSetAsDefaultPrompt( + nimbusFeature: DefaultBrowserPrompt = FxNimbus.features.defaultBrowserPrompt.value(), + ): Boolean { + if (!nimbusFeature.enabled) return false + + val now = System.currentTimeMillis() + + val daysOk = nimbusFeature.daysBetweenPrompts?.let { intervalDays -> + (now - lastSetAsDefaultPromptShownTimeInMillis) > intervalDays * ONE_DAY_MS + } ?: true + + val maxOk = nimbusFeature.maxPromptsShown?.let { max -> + numberOfSetAsDefaultPromptShownTimes < max + } ?: true + + val coldStartsOk = nimbusFeature.coldStartsBetweenPrompts?.let { minColdStarts -> + coldStartsBetweenSetAsDefaultPrompts >= minColdStarts + } ?: true + + return daysOk && maxOk && coldStartsOk + } /** * Updates the relevant settings when the "Set as Default Browser" prompt is shown. diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -25,6 +25,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.toolbar.ToolbarPosition +import org.mozilla.fenix.nimbus.DefaultBrowserPrompt import org.mozilla.fenix.nimbus.FakeNimbusEventStore import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitType @@ -1152,7 +1153,7 @@ class SettingsTest { settings.lastSetAsDefaultPromptShownTimeInMillis = System.currentTimeMillis() settings.coldStartsBetweenSetAsDefaultPrompts = 5 - assertFalse(settings.shouldShowSetAsDefaultPrompt) + assertFalse(settings.shouldShowSetAsDefaultPrompt()) } @Test @@ -1161,7 +1162,7 @@ class SettingsTest { settings.lastSetAsDefaultPromptShownTimeInMillis = 0L settings.coldStartsBetweenSetAsDefaultPrompts = 5 - assertFalse(settings.shouldShowSetAsDefaultPrompt) + assertFalse(settings.shouldShowSetAsDefaultPrompt()) } @Test @@ -1170,7 +1171,7 @@ class SettingsTest { settings.lastSetAsDefaultPromptShownTimeInMillis = System.currentTimeMillis() - 1000 settings.coldStartsBetweenSetAsDefaultPrompts = 5 - assertFalse(settings.shouldShowSetAsDefaultPrompt) + assertFalse(settings.shouldShowSetAsDefaultPrompt()) } @Test @@ -1179,7 +1180,7 @@ class SettingsTest { settings.lastSetAsDefaultPromptShownTimeInMillis = 0L settings.coldStartsBetweenSetAsDefaultPrompts = 1 - assertFalse(settings.shouldShowSetAsDefaultPrompt) + assertFalse(settings.shouldShowSetAsDefaultPrompt()) } @Test @@ -1188,7 +1189,67 @@ class SettingsTest { settings.lastSetAsDefaultPromptShownTimeInMillis = 0L settings.coldStartsBetweenSetAsDefaultPrompts = 5 // More than required cold starts - assertTrue(settings.shouldShowSetAsDefaultPrompt) + assertTrue(settings.shouldShowSetAsDefaultPrompt()) + } + + @Test + fun `GIVEN other conditions are valid WHEN the default browser prompt is disabled THEN shouldShowSetAsDefaultPrompt is false`() { + settings.numberOfSetAsDefaultPromptShownTimes = 1 + settings.lastSetAsDefaultPromptShownTimeInMillis = 0L + settings.coldStartsBetweenSetAsDefaultPrompts = 5 // More than required cold starts + + assertFalse( + settings.shouldShowSetAsDefaultPrompt( + DefaultBrowserPrompt( + enabled = false, + ), + ), + ) + } + + @Test + fun `GIVEN other conditions are valid WHEN the days between prompts is null THEN the value is ignored`() { + settings.numberOfSetAsDefaultPromptShownTimes = 1 + settings.lastSetAsDefaultPromptShownTimeInMillis = System.currentTimeMillis() + settings.coldStartsBetweenSetAsDefaultPrompts = 5 + + assertTrue( + settings.shouldShowSetAsDefaultPrompt( + DefaultBrowserPrompt( + daysBetweenPrompts = null, + ), + ), + ) + } + + @Test + fun `GIVEN other conditions are valid WHEN max prompts shown is null THEN the value is ignored`() { + settings.numberOfSetAsDefaultPromptShownTimes = 10 + settings.lastSetAsDefaultPromptShownTimeInMillis = 0L + settings.coldStartsBetweenSetAsDefaultPrompts = 5 + + assertTrue( + settings.shouldShowSetAsDefaultPrompt( + DefaultBrowserPrompt( + maxPromptsShown = null, + ), + ), + ) + } + + @Test + fun `GIVEN other conditions are valid WHEN cold starts between prompts is null THEN the value is ignored`() { + settings.numberOfSetAsDefaultPromptShownTimes = 1 + settings.lastSetAsDefaultPromptShownTimeInMillis = 0L + settings.coldStartsBetweenSetAsDefaultPrompts = 0 + + assertTrue( + settings.shouldShowSetAsDefaultPrompt( + DefaultBrowserPrompt( + coldStartsBetweenPrompts = null, + ), + ), + ) } @Test