Verified Commit 8801c542 authored by clairehurst's avatar clairehurst 🌱 Committed by Pier Angelo Vendrame
Browse files

[android] Implement Android-native Connection Assist UI

parent 423ecb52
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,4 +42,5 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) {
    FromTranslationsDialogFragment(R.id.translationsDialogFragment),
    FromDownloadLanguagesPreferenceFragment(R.id.downloadLanguagesPreferenceFragment),
    FromMenuDialogFragment(R.id.menuDialogFragment),
    FromTorConnectionAssistFragment(R.id.torConnectionAssistFragment),
}
+66 −4
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.WindowManager.LayoutParams.FLAG_SECURE
import androidx.activity.viewModels
import androidx.annotation.CallSuper
import androidx.annotation.IdRes
import androidx.annotation.RequiresApi
@@ -33,7 +34,6 @@ import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.ActionBar
import androidx.appcompat.widget.Toolbar
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
@@ -81,6 +81,7 @@ import mozilla.components.support.utils.BrowsersCache
import mozilla.components.support.utils.ManufacturerCodes
import mozilla.components.support.utils.SafeIntent
import mozilla.components.support.utils.TorUtils
import mozilla.components.support.utils.ext.getParcelableExtraCompat
import mozilla.components.support.utils.toSafeIntent
import mozilla.components.support.webextensions.WebExtensionPopupObserver
import mozilla.telemetry.glean.private.NoExtras
@@ -145,11 +146,18 @@ import org.mozilla.fenix.tabhistory.TabHistoryDialogFragment
import org.mozilla.fenix.tabstray.TabsTrayFragment
import org.mozilla.fenix.theme.DefaultThemeManager
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections
import org.mozilla.fenix.tor.TorEvents
import org.mozilla.fenix.utils.Settings
import java.lang.ref.WeakReference
import java.util.Locale

import mozilla.components.browser.engine.gecko.GeckoEngine
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.home.HomeFragment
import org.mozilla.fenix.tor.TorConnectionAssistViewModel
import org.mozilla.geckoview.TorIntegrationAndroid

/**
 * The main activity of the application. The application is primarily a single Activity (this one)
 * with fragments switching out to display different views. The most important views shown here are the:
@@ -157,7 +165,7 @@ import java.util.Locale
 * - browser screen
 */
@SuppressWarnings("TooManyFunctions", "LargeClass", "LongMethod")
open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIntegrationAndroid.BootstrapStateChangeListener {
    private lateinit var binding: ActivityHomeBinding
    lateinit var themeManager: ThemeManager
    lateinit var browsingModeManager: BrowsingModeManager
@@ -229,6 +237,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {

    private var dialog: RedirectDialogFragment? = null

    private val torConnectionAssistViewModel: TorConnectionAssistViewModel by viewModels()

    @Suppress("ComplexMethod")
    final override fun onCreate(savedInstanceState: Bundle?) {
        // DO NOT MOVE ANYTHING ABOVE THIS getProfilerTime CALL.
@@ -442,6 +452,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {

        components.notificationsDelegate.bindToActivity(this)

        val engine = components.core.engine
        if (engine is GeckoEngine) {
            val torIntegration = engine.getTorIntegrationController()
            torIntegration.registerBootstrapStateChangeListener(this)
        }

        StartupTimeline.onActivityCreateEndHome(this) // DO NOT MOVE ANYTHING BELOW HERE.
    }

@@ -606,8 +622,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
    override fun onProvideAssistContent(outContent: AssistContent?) {
        super.onProvideAssistContent(outContent)
        val currentTabUrl = components.core.store.state.selectedTab?.content?.url
        if (components.core.store.state.selectedTab?.content?.private == false) {
            outContent?.webUri = currentTabUrl?.let { Uri.parse(it) }
        }
    }

    @CallSuper
    override fun onDestroy() {
@@ -641,6 +659,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
            // underlying Application, as well.
            (application as FenixApplication).terminate()
        }

        val engine = components.core.engine
        if (engine is GeckoEngine) {
            val torIntegration = engine.getTorIntegrationController()
            torIntegration.unregisterBootstrapStateChangeListener(this)
        }
    }

    final override fun onConfigurationChanged(newConfig: Configuration) {
@@ -1089,6 +1113,25 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
        historyMetadata: HistoryMetadataKey? = null,
        additionalHeaders: Map<String, String>? = null,
    ) {
        if (!components.torController.isBootstrapped && !searchTermOrURL.startsWith("about:")) {
            FenixSnackbar.make(
                view = binding.root,
                isDisplayedWithBrowserToolbar = true,
            )
                .setText(getString(R.string.connection_assist_connect_to_tor_before_opening_links))
                .setAction(getString(R.string.connection_assist_connect_to_tor_before_opening_links_confirmation)) {
                    torConnectionAssistViewModel.handleConnect(searchTermOrURL)
                    if (navHost.navController.previousBackStackEntry?.destination?.id == R.id.torConnectionAssistFragment) {
                        supportFragmentManager.popBackStack()
                    } else {
                        navHost.navController.navigate(
                            TorConnectionAssistFragmentDirections.actionConnectToTorBeforeOpeningLinks()
                        )
                    }
                }
                .show()
            return
        }
        openToBrowser(from, customTabSessionId)
        load(
            searchTermOrURL = searchTermOrURL,
@@ -1228,7 +1271,16 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
        //    return
        //}

        navHost.navController.navigate(NavGraphDirections.actionStartupTorbootstrap())
        if (!settings().useHtmlConnectionUi) {
            navController.navigate(NavGraphDirections.actionStartupTorConnectionAssist())
        } else {
            navController.navigate(NavGraphDirections.actionStartupHome())
            openToBrowserAndLoad(
                searchTermOrURL = "about:torconnect",
                newTab = true,
                from = BrowserDirection.FromHome,
            )
        }
    }

    final override fun attachBaseContext(base: Context) {
@@ -1395,4 +1447,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
        // telemetry purposes.
        private const val PWA_RECENTLY_USED_THRESHOLD = DateUtils.DAY_IN_MILLIS * 30L
    }

    override fun onBootstrapStateChange(state: String) = Unit
    override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit
    override fun onBootstrapComplete() {
        if (settings().useHtmlConnectionUi) {
            components.useCases.tabsUseCases.removeAllTabs()
            navHost.navController.navigate(NavGraphDirections.actionStartupHome())
        }
    }
    override fun onBootstrapError(code: String?, message: String?, phase: String?, reason: String?) = Unit
}
+19 −0
Original line number Diff line number Diff line
@@ -1752,6 +1752,9 @@ abstract class BaseBrowserFragment :
                val bottomToolbarHeight = context.settings().getBottomToolbarHeight()
                resumeDownloadDialogState(selectedTab.id, context.components.core.store, context, bottomToolbarHeight)
                it.announceForAccessibility(selectedTab.toDisplayTitle())
                if (getCurrentTab()?.content?.url == "about:torconnect") {
                    browserToolbarView.view.visibility = View.GONE
                }
            }
        } else {
            view?.let { view -> initializeUI(view) }
@@ -1776,6 +1779,22 @@ abstract class BaseBrowserFragment :
                    openLinksInExternalApp
                }
            }
        handleBetaHtmlTorConnect()
    }

    private fun handleBetaHtmlTorConnect() {
        val currentTab = getCurrentTab() ?: return
        if (currentTab.content.url == "about:torconnect") {
            if (!requireActivity().settings().useHtmlConnectionUi) {
                requireContext().components.useCases.tabsUseCases.removeTab(currentTab.id)
                (requireActivity() as HomeActivity).navigateToHome(findNavController())
            } else {
                // This just makes it not flash (be visible for a split second) before handleTabSelected() hides it again
                browserToolbarView.view.visibility = View.GONE
            }
        } else if (currentTab.content.url == "about:tor") {
            requireContext().components.useCases.tabsUseCases.removeTab(currentTab.id)
        }
    }

    @CallSuper
+4 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import org.mozilla.fenix.settings.wallpaper.WallpaperSettingsFragmentDirections
import org.mozilla.fenix.share.AddNewDeviceFragmentDirections
import org.mozilla.fenix.shopping.ReviewQualityCheckFragmentDirections
import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections
import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections
import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections
import org.mozilla.fenix.translations.TranslationsDialogFragmentDirections
import org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguagesPreferenceFragmentDirections
@@ -330,6 +331,9 @@ private fun getHomeNavDirections(

    BrowserDirection.FromDownloadLanguagesPreferenceFragment ->
        DownloadLanguagesPreferenceFragmentDirections.actionGlobalBrowser()

    BrowserDirection.FromTorConnectionAssistFragment ->
        TorConnectionAssistFragmentDirections.actionGlobalBrowser()
}

const val REQUEST_CODE_BROWSER_ROLE = 1
+20 −1
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ import mozilla.components.feature.top.sites.TopSitesProviderConfig
import mozilla.components.lib.state.ext.consumeFlow
import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.service.glean.private.NoExtras
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.ui.colors.PhotonColors
import mozilla.components.ui.tabcounter.TabCounterMenu
@@ -173,6 +174,7 @@ import org.mozilla.fenix.tabstray.TabsTrayAccessPoint
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.tor.TorBootstrapFragmentDirections
import org.mozilla.fenix.tor.TorBootstrapStatus
import org.mozilla.fenix.tor.TorConnectionAssistViewModel
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wallpapers.Wallpaper
@@ -180,7 +182,7 @@ import java.lang.ref.WeakReference
import org.mozilla.fenix.GleanMetrics.TabStrip as TabStripMetrics

@Suppress("TooManyFunctions", "LargeClass")
class HomeFragment : Fragment() {
class HomeFragment : Fragment(), UserInteractionHandler {
    private val args by navArgs<HomeFragmentArgs>()

    @VisibleForTesting
@@ -192,6 +194,7 @@ class HomeFragment : Fragment() {
    internal val binding get() = _binding!!

    private val homeViewModel: HomeScreenViewModel by activityViewModels()
    private val torConnectionAssistViewModel: TorConnectionAssistViewModel by activityViewModels()

    private val snackbarAnchorView: View?
        get() = when (requireContext().settings().toolbarPosition) {
@@ -1105,6 +1108,17 @@ class HomeFragment : Fragment() {
            view = view,
        )

        torConnectionAssistViewModel.urlToLoadAfterConnecting.also {
            if(!it.isNullOrBlank()){
                (requireActivity() as HomeActivity).openToBrowserAndLoad(
                    searchTermOrURL = it,
                    newTab = true,
                    from = BrowserDirection.FromHome,
                )
                torConnectionAssistViewModel.urlToLoadAfterConnecting = null // Only load this url once
            }
        }

        // DO NOT MOVE ANYTHING BELOW THIS addMarker CALL!
        requireComponents.core.engine.profiler?.addMarker(
            MarkersFragmentLifecycleCallbacks.MARKER_NAME,
@@ -1623,4 +1637,9 @@ class HomeFragment : Fragment() {
        // Elevation for undo toasts
        internal const val TOAST_ELEVATION = 80f
    }

    override fun onBackPressed(): Boolean {
        requireActivity().finish()
        return true
    }
}
Loading