Commits:
-
0f6d7a42
by clairehurst at 2026-09-02T17:12:51-06:00
fixup! [android] Implement Android-native Connection Assist UI
Bug 45172: Move away from openToBrowserAndLoad()
-
56c0e22d
by clairehurst at 2026-09-02T17:13:21-06:00
fixup! [android] Modify UI/UX
Bug 45172: Move away from openToBrowserAndLoad()
12 changed files:
Changes:
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
| ... |
... |
@@ -1475,30 +1475,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash |
|
1475
|
1475
|
historyMetadata: HistoryMetadataKey? = null,
|
|
1476
|
1476
|
additionalHeaders: Map<String, String>? = null,
|
|
1477
|
1477
|
) {
|
|
1478
|
|
- if (!components.torController.isBootstrapped && !searchTermOrURL.startsWith("about:")) {
|
|
1479
|
|
- Snackbar.make(
|
|
1480
|
|
- snackBarParentView = binding.root,
|
|
1481
|
|
- snackbarState = SnackbarState(
|
|
1482
|
|
- message = getString(R.string.connection_assist_connect_to_tor_before_opening_links),
|
|
1483
|
|
- duration = SnackbarState.Duration.Preset.Long,
|
|
1484
|
|
- action = Action(
|
|
1485
|
|
- label = getString(R.string.connection_assist_connect_to_tor_before_opening_links_confirmation),
|
|
1486
|
|
- onClick = {
|
|
1487
|
|
- urlQuickLoadViewModel.urlToLoadAfterConnecting.value = searchTermOrURL
|
|
1488
|
|
- urlQuickLoadViewModel.maybeBeginBootstrap()
|
|
1489
|
|
- if (navHost.navController.previousBackStackEntry?.destination?.id == R.id.torConnectionAssistFragment) {
|
|
1490
|
|
- supportFragmentManager.popBackStack()
|
|
1491
|
|
- } else {
|
|
1492
|
|
- navHost.navController.navigate(
|
|
1493
|
|
- TorConnectionAssistFragmentDirections.actionConnectToTorBeforeOpeningLinks(),
|
|
1494
|
|
- )
|
|
1495
|
|
- }
|
|
1496
|
|
- },
|
|
1497
|
|
- ),
|
|
1498
|
|
- ),
|
|
1499
|
|
- ).show()
|
|
1500
|
|
- return
|
|
1501
|
|
- }
|
|
|
1478
|
+ if (maybeShowConnectToTorPrompt(url = searchTermOrURL)) return
|
|
1502
|
1479
|
openToBrowser(from, customTabSessionId)
|
|
1503
|
1480
|
|
|
1504
|
1481
|
components.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
| ... |
... |
@@ -1813,4 +1790,37 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash |
|
1813
|
1790
|
e.printStackTrace()
|
|
1814
|
1791
|
}
|
|
1815
|
1792
|
}
|
|
|
1793
|
+
|
|
|
1794
|
+ /**
|
|
|
1795
|
+ * @return `true` if not connected to tor and the prompt attempted to be shown.
|
|
|
1796
|
+ * `false` if connected to tor and prompt does not need to be shown
|
|
|
1797
|
+ */
|
|
|
1798
|
+ fun maybeShowConnectToTorPrompt(url: String) : Boolean {
|
|
|
1799
|
+ if (!components.torController.isBootstrapped && !url.startsWith("about:")) {
|
|
|
1800
|
+ Snackbar.make(
|
|
|
1801
|
+ snackBarParentView = binding.root,
|
|
|
1802
|
+ snackbarState = SnackbarState(
|
|
|
1803
|
+ message = getString(R.string.connection_assist_connect_to_tor_before_opening_links),
|
|
|
1804
|
+ duration = SnackbarState.Duration.Preset.Long,
|
|
|
1805
|
+ action = Action(
|
|
|
1806
|
+ label = getString(R.string.connection_assist_connect_to_tor_before_opening_links_confirmation),
|
|
|
1807
|
+ onClick = {
|
|
|
1808
|
+ urlQuickLoadViewModel.urlToLoadAfterConnecting.value = url
|
|
|
1809
|
+ urlQuickLoadViewModel.maybeBeginBootstrap()
|
|
|
1810
|
+ if (navHost.navController.previousBackStackEntry?.destination?.id == R.id.torConnectionAssistFragment) {
|
|
|
1811
|
+ supportFragmentManager.popBackStack()
|
|
|
1812
|
+ } else {
|
|
|
1813
|
+ navHost.navController.navigate(
|
|
|
1814
|
+ TorConnectionAssistFragmentDirections.actionConnectToTorBeforeOpeningLinks(),
|
|
|
1815
|
+ )
|
|
|
1816
|
+ }
|
|
|
1817
|
+ },
|
|
|
1818
|
+ ),
|
|
|
1819
|
+ ),
|
|
|
1820
|
+ ).show()
|
|
|
1821
|
+ return true
|
|
|
1822
|
+ } else {
|
|
|
1823
|
+ return false
|
|
|
1824
|
+ }
|
|
|
1825
|
+ }
|
|
1816
|
1826
|
} |
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsFragment.kt
| ... |
... |
@@ -19,6 +19,7 @@ import mozilla.components.feature.addons.Addon |
|
19
|
19
|
import mozilla.components.feature.addons.ui.showInformationDialog
|
|
20
|
20
|
import mozilla.components.feature.addons.ui.translateName
|
|
21
|
21
|
import mozilla.components.feature.addons.update.DefaultAddonUpdater.UpdateAttemptStorage
|
|
|
22
|
+import org.mozilla.fenix.HomeActivity
|
|
22
|
23
|
import org.mozilla.fenix.R
|
|
23
|
24
|
import org.mozilla.fenix.databinding.FragmentAddOnDetailsBinding
|
|
24
|
25
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
| ... |
... |
@@ -51,6 +52,7 @@ class AddonDetailsFragment : |
|
51
|
52
|
}
|
|
52
|
53
|
|
|
53
|
54
|
override fun openWebsite(url: Uri) {
|
|
|
55
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(url.toString())) return
|
|
54
|
56
|
findNavController().openToBrowser()
|
|
55
|
57
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
56
|
58
|
searchTermOrURL = url.toString(),
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/AddonPermissionsDetailsFragment.kt
| ... |
... |
@@ -17,6 +17,7 @@ import androidx.navigation.fragment.navArgs |
|
17
|
17
|
import mozilla.components.feature.addons.Addon
|
|
18
|
18
|
import mozilla.components.feature.addons.Addon.Companion.isAllURLsPermission
|
|
19
|
19
|
import mozilla.components.feature.addons.ui.translateName
|
|
|
20
|
+import org.mozilla.fenix.HomeActivity
|
|
20
|
21
|
import org.mozilla.fenix.addons.ui.AddonPermissionsScreen
|
|
21
|
22
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
|
22
|
23
|
import org.mozilla.fenix.ext.components
|
| ... |
... |
@@ -171,6 +172,7 @@ class AddonPermissionsDetailsFragment : Fragment(), SystemInsetsPaddedFragment { |
|
171
|
172
|
}
|
|
172
|
173
|
|
|
173
|
174
|
private fun openWebsite(addonSiteUrl: String) {
|
|
|
175
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(addonSiteUrl)) return
|
|
174
|
176
|
findNavController().openToBrowser()
|
|
175
|
177
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
176
|
178
|
searchTermOrURL = addonSiteUrl,
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/AddonsManagementFragment.kt
| ... |
... |
@@ -26,6 +26,7 @@ import mozilla.components.feature.addons.Addon |
|
26
|
26
|
import mozilla.components.feature.addons.AddonManager
|
|
27
|
27
|
import mozilla.components.feature.addons.AddonManagerException
|
|
28
|
28
|
import mozilla.components.feature.addons.ui.AddonsManagerAdapter
|
|
|
29
|
+import org.mozilla.fenix.HomeActivity
|
|
29
|
30
|
import org.mozilla.fenix.R
|
|
30
|
31
|
import org.mozilla.fenix.databinding.FragmentAddOnsManagementBinding
|
|
31
|
32
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
| ... |
... |
@@ -76,6 +77,7 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management), |
|
76
|
77
|
onInstallButtonClicked = ::installAddon,
|
|
77
|
78
|
onMoreAddonsButtonClicked = ::openAMO,
|
|
78
|
79
|
onLearnMoreClicked = { link, addon ->
|
|
|
80
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(resolveLearnMoreUrl(link, addon) ?: return@AddonsManagementView)) return@AddonsManagementView
|
|
79
|
81
|
binding?.root?.openLearnMoreLink(link, addon)
|
|
80
|
82
|
},
|
|
81
|
83
|
)
|
| ... |
... |
@@ -204,6 +206,7 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management), |
|
204
|
206
|
}
|
|
205
|
207
|
|
|
206
|
208
|
private fun openAMO() {
|
|
|
209
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(AMO_HOMEPAGE_FOR_ANDROID)) return
|
|
207
|
210
|
findNavController().openToBrowser()
|
|
208
|
211
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
209
|
212
|
searchTermOrURL = AMO_HOMEPAGE_FOR_ANDROID,
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/Extensions.kt
| ... |
... |
@@ -48,7 +48,7 @@ internal fun View.openLearnMoreLink( |
|
48
|
48
|
)
|
|
49
|
49
|
}
|
|
50
|
50
|
|
|
51
|
|
-private fun resolveLearnMoreUrl(
|
|
|
51
|
+fun resolveLearnMoreUrl(
|
|
52
|
52
|
link: AddonsManagerAdapterDelegate.LearnMoreLinks,
|
|
53
|
53
|
addon: Addon,
|
|
54
|
54
|
): String? {
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt
| ... |
... |
@@ -30,6 +30,7 @@ import mozilla.components.support.ktx.android.content.appName |
|
30
|
30
|
import mozilla.components.support.ktx.android.content.appVersionName
|
|
31
|
31
|
import org.mozilla.fenix.BuildConfig
|
|
32
|
32
|
import mozilla.components.support.webextensions.WebExtensionSupport.installedExtensions
|
|
|
33
|
+import org.mozilla.fenix.HomeActivity
|
|
33
|
34
|
import org.mozilla.fenix.databinding.FragmentInstalledAddOnDetailsBinding
|
|
34
|
35
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
|
35
|
36
|
import org.mozilla.fenix.ext.components
|
| ... |
... |
@@ -174,6 +175,7 @@ class InstalledAddonDetailsFragment : Fragment(), SystemInsetsPaddedFragment { |
|
174
|
175
|
messageBarWarningView,
|
|
175
|
176
|
messageBarErrorView,
|
|
176
|
177
|
onLearnMoreLinkClicked = { link ->
|
|
|
178
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(resolveLearnMoreUrl(link, addon) ?: return@bindMessageBars)) return@bindMessageBars
|
|
177
|
179
|
binding.root.openLearnMoreLink(link, addon)
|
|
178
|
180
|
},
|
|
179
|
181
|
addon,
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt
| ... |
... |
@@ -1079,6 +1079,7 @@ class MenuDialogFragment : BottomSheetDialogFragment() { |
|
1079
|
1079
|
}
|
|
1080
|
1080
|
|
|
1081
|
1081
|
url?.let {
|
|
|
1082
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(url)) return@let
|
|
1082
|
1083
|
findNavController().openToBrowser()
|
|
1083
|
1084
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
1084
|
1085
|
searchTermOrURL = url,
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
| ... |
... |
@@ -552,11 +552,13 @@ class HomeFragment : Fragment(), UserInteractionHandler { |
|
552
|
552
|
|
|
553
|
553
|
urlQuickLoadViewModel.urlToLoadAfterConnecting.observe(viewLifecycleOwner) {
|
|
554
|
554
|
if (!it.isNullOrBlank()) {
|
|
555
|
|
- @Suppress("DEPRECATION")
|
|
556
|
|
- (requireActivity() as HomeActivity).openToBrowserAndLoad(
|
|
|
555
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(it)) return@observe
|
|
|
556
|
+ (requireActivity() as HomeActivity).openToBrowser(
|
|
|
557
|
+ from = BrowserDirection.FromHome,
|
|
|
558
|
+ )
|
|
|
559
|
+ requireContext().components.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
557
|
560
|
searchTermOrURL = it,
|
|
558
|
561
|
newTab = true,
|
|
559
|
|
- from = BrowserDirection.FromHome,
|
|
560
|
562
|
)
|
|
561
|
563
|
// Only load this url once
|
|
562
|
564
|
urlQuickLoadViewModel.urlToLoadAfterConnecting.value = null
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HttpsOnlyFragment.kt
| ... |
... |
@@ -18,6 +18,7 @@ import androidx.core.view.children |
|
18
|
18
|
import androidx.core.view.isGone
|
|
19
|
19
|
import androidx.fragment.app.Fragment
|
|
20
|
20
|
import androidx.navigation.fragment.findNavController
|
|
|
21
|
+import org.mozilla.fenix.HomeActivity
|
|
21
|
22
|
import org.mozilla.fenix.R
|
|
22
|
23
|
import org.mozilla.fenix.databinding.SettingsHttpsOnlyBinding
|
|
23
|
24
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
| ... |
... |
@@ -105,6 +106,7 @@ class HttpsOnlyFragment : Fragment(), SystemInsetsPaddedFragment { |
|
105
|
106
|
val linkClickListener: ClickableSpan = object : ClickableSpan() {
|
|
106
|
107
|
override fun onClick(view: View) {
|
|
107
|
108
|
view.setOnClickListener {
|
|
|
109
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(SupportUtils.DONATE_URL)) return@setOnClickListener
|
|
108
|
110
|
findNavController().openToBrowser()
|
|
109
|
111
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
110
|
112
|
searchTermOrURL = SupportUtils.getGenericSumoURLForTopic(
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
| ... |
... |
@@ -96,6 +96,7 @@ import mozilla.components.ui.icons.R as iconsR |
|
96
|
96
|
import org.mozilla.fenix.GleanMetrics.Settings as SettingsMetrics
|
|
97
|
97
|
|
|
98
|
98
|
import android.view.WindowManager
|
|
|
99
|
+import org.mozilla.fenix.ext.openToBrowser
|
|
99
|
100
|
|
|
100
|
101
|
/**
|
|
101
|
102
|
* Main settings screen.
|
| ... |
... |
@@ -560,15 +561,16 @@ class SettingsFragment : PreferenceFragmentCompat(), SystemInsetsPaddedFragment, |
|
560
|
561
|
SettingsFragmentDirections.actionSettingsFragmentToAboutFragment()
|
|
561
|
562
|
}
|
|
562
|
563
|
|
|
563
|
|
- resources.getString(R.string.pref_key_donate) -> {
|
|
564
|
|
- @Suppress("DEPRECATION")
|
|
565
|
|
- (activity as HomeActivity).openToBrowserAndLoad(
|
|
566
|
|
- searchTermOrURL = SupportUtils.DONATE_URL,
|
|
567
|
|
- newTab = true,
|
|
568
|
|
- from = BrowserDirection.FromSettings
|
|
569
|
|
- )
|
|
570
|
|
- null
|
|
571
|
|
- }
|
|
|
564
|
+ resources.getString(R.string.pref_key_donate) ->
|
|
|
565
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(SupportUtils.DONATE_URL)) null
|
|
|
566
|
+ else {
|
|
|
567
|
+ findNavController().openToBrowser()
|
|
|
568
|
+ requireContext().components.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
|
569
|
+ searchTermOrURL = SupportUtils.DONATE_URL,
|
|
|
570
|
+ newTab = true,
|
|
|
571
|
+ )
|
|
|
572
|
+ null
|
|
|
573
|
+ }
|
|
572
|
574
|
|
|
573
|
575
|
// Only displayed when secret settings are enabled
|
|
574
|
576
|
resources.getString(R.string.pref_key_debug_settings) -> {
|
| ... |
... |
@@ -825,12 +827,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SystemInsetsPaddedFragment, |
|
825
|
827
|
requirePreference<Preference>(R.string.pref_key_about_config_shortcut).apply {
|
|
826
|
828
|
isVisible = requireContext().components.settings.showSecretDebugMenuThisSession || Config.channel == ReleaseChannel.Debug
|
|
827
|
829
|
setOnPreferenceClickListener {
|
|
828
|
|
- @Suppress("DEPRECATION")
|
|
829
|
|
- (requireActivity() as HomeActivity).openToBrowserAndLoad(
|
|
830
|
|
- searchTermOrURL = "about:config",
|
|
831
|
|
- from = BrowserDirection.FromSettings,
|
|
832
|
|
- newTab = true,
|
|
833
|
|
- )
|
|
|
830
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt("about:config")) return@setOnPreferenceClickListener true
|
|
|
831
|
+ findNavController().openToBrowser()
|
|
|
832
|
+ components.useCases.fenixBrowserUseCases.loadUrlOrSearch("about:config", newTab = true)
|
|
834
|
833
|
true
|
|
835
|
834
|
}
|
|
836
|
835
|
}
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt
| ... |
... |
@@ -38,6 +38,8 @@ import org.mozilla.fenix.utils.Settings |
|
38
|
38
|
import org.mozilla.fenix.whatsnew.WhatsNew
|
|
39
|
39
|
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
|
40
|
40
|
|
|
|
41
|
+import org.mozilla.fenix.HomeActivity
|
|
|
42
|
+
|
|
41
|
43
|
/**
|
|
42
|
44
|
* Displays the logo and information about the app, including library versions.
|
|
43
|
45
|
*/
|
| ... |
... |
@@ -244,6 +246,7 @@ class AboutFragment( |
|
244
|
246
|
}
|
|
245
|
247
|
|
|
246
|
248
|
private fun openLinkInNormalTab(url: String) {
|
|
|
249
|
+ if ((requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(url)) return
|
|
247
|
250
|
findNavController().openToBrowser()
|
|
248
|
251
|
requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
249
|
252
|
searchTermOrURL = url,
|
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/search/SaveSearchEngineFragment.kt
| ... |
... |
@@ -17,6 +17,7 @@ import kotlinx.coroutines.launch |
|
17
|
17
|
import mozilla.components.browser.icons.IconRequest
|
|
18
|
18
|
import mozilla.components.feature.search.ext.createSearchEngine
|
|
19
|
19
|
import org.mozilla.fenix.GleanMetrics.Events
|
|
|
20
|
+import org.mozilla.fenix.HomeActivity
|
|
20
|
21
|
import org.mozilla.fenix.R
|
|
21
|
22
|
import org.mozilla.fenix.databinding.FragmentSaveSearchEngineBinding
|
|
22
|
23
|
import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
| ... |
... |
@@ -85,14 +86,17 @@ class SaveSearchEngineFragment : Fragment(R.layout.fragment_save_search_engine), |
|
85
|
86
|
}
|
|
86
|
87
|
|
|
87
|
88
|
val learnMoreListener: (View) -> Unit = {
|
|
88
|
|
- findNavController().openToBrowser()
|
|
89
|
|
- requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
90
|
|
- searchTermOrURL = SupportUtils.getSumoURLForTopic(
|
|
91
|
|
- requireContext(),
|
|
92
|
|
- SupportUtils.SumoTopic.CUSTOM_SEARCH_ENGINES,
|
|
93
|
|
- ),
|
|
94
|
|
- newTab = true,
|
|
|
89
|
+ val url = SupportUtils.getSumoURLForTopic(
|
|
|
90
|
+ requireContext(),
|
|
|
91
|
+ SupportUtils.SumoTopic.CUSTOM_SEARCH_ENGINES,
|
|
95
|
92
|
)
|
|
|
93
|
+ if (!(requireActivity() as HomeActivity).maybeShowConnectToTorPrompt(url)) {
|
|
|
94
|
+ findNavController().openToBrowser()
|
|
|
95
|
+ requireComponents.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
|
96
|
+ searchTermOrURL = url,
|
|
|
97
|
+ newTab = true,
|
|
|
98
|
+ )
|
|
|
99
|
+ }
|
|
96
|
100
|
}
|
|
97
|
101
|
binding.customSearchEnginesLearnMoreWrapper.setOnClickListener(learnMoreListener)
|
|
98
|
102
|
binding.customSearchSuggestionsLearnMoreWrapper.setOnClickListener(learnMoreListener)
|
|