Commit 4d96eb68 authored by Matthew Finkel's avatar Matthew Finkel
Browse files

Bug 40028: Integrate Tor Controller into HomeFragment

parent b4d323b9
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import org.mozilla.fenix.push.WebPushEngineIntegration
import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
import org.mozilla.fenix.session.VisibilityLifecycleCallback
import org.mozilla.fenix.utils.BrowsersCache
import org.torproject.android.service.util.Prefs

/**
 *The main application class for Fenix. Records data to measure initialization performance.
@@ -62,6 +63,8 @@ open class FenixApplication : LocaleAwareApplication(), Provider {

    private val logger = Logger("FenixApplication")

    var terminating = false

    open val components by lazy { Components(this) }

    var visibilityLifecycleCallback: VisibilityLifecycleCallback? = null
@@ -91,6 +94,21 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
        setupInMainProcessOnly()
    }

    fun isTerminating() = terminating

    fun terminate() {
        onTerminate()
        System.exit(0)
    }

    override fun onTerminate() {
        terminating = true

        super.onTerminate()
        components.torController.stop()
        components.torController.stopTor()
    }

    protected open fun initializeGlean() {
        val telemetryEnabled = settings().isTelemetryEnabled

@@ -139,6 +157,11 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
            if (!megazordSetup.isCompleted) {
                runBlocking { megazordSetup.await(); }
            }

            GlobalScope.launch(Dispatchers.IO) {
                // Give TAS the base Context
                Prefs.setContext(applicationContext)
            }
        }

        setupLeakCanary()
@@ -157,6 +180,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
        initVisualCompletenessQueueAndQueueTasks()

        components.appStartupTelemetry.onFenixApplicationOnCreate()
        components.torController.start()
    }

    private fun restoreDownloads() {
+13 −9
Original line number Diff line number Diff line
@@ -4,10 +4,9 @@

package org.mozilla.fenix

import android.content.BroadcastReceiver
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
@@ -26,7 +25,6 @@ import androidx.annotation.VisibleForTesting.PROTECTED
import androidx.appcompat.app.ActionBar
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.navigation.NavDestination
import androidx.navigation.NavDirections
import androidx.navigation.fragment.NavHostFragment
@@ -104,9 +102,6 @@ import org.mozilla.fenix.tabtray.TabTrayDialogFragmentDirections
import org.mozilla.fenix.theme.DefaultThemeManager
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.BrowsersCache
import org.torproject.android.service.TorService
import org.torproject.android.service.TorServiceConstants
import org.torproject.android.service.util.Prefs
import java.lang.ref.WeakReference

/**
@@ -135,6 +130,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {

    private var isToolbarInflated = false

    private var isBeingRecreated = false

    private val webExtensionPopupFeature by lazy {
        WebExtensionPopupFeature(components.core.store, ::openPopup)
    }
@@ -159,9 +156,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
    private lateinit var navigationToolbar: Toolbar

    final override fun onCreate(savedInstanceState: Bundle?) {
        // Give Orbot the base Context
        Prefs.setContext(applicationContext)

        components.strictMode.attachListenerToDisablePenaltyDeath(supportFragmentManager)

        // There is disk read violations on some devices such as samsung and pixel for android 9/10
@@ -380,6 +374,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
        )

        privateNotificationObserver?.stop()
        if (!isBeingRecreated && !(application as FenixApplication).isTerminating()) {
            // We assume the Activity is being destroyed because the user
            // swiped away the app on the Recent screen. When this happens,
            // we assume the user expects the entire Application is destroyed
            // and not only the top Activity/Task. Therefore we kill the
            // underlying Application, as well.
            (application as FenixApplication).terminate()
        }
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
@@ -399,6 +401,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
            message = "recreate()"
        )

        isBeingRecreated = true

        super.recreate()
    }

+3 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.StrictModeManager
import org.mozilla.fenix.components.metrics.AppStartupTelemetry
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.tor.TorController
import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Mockable
import org.mozilla.fenix.utils.Settings
@@ -142,4 +143,6 @@ class Components(private val context: Context) {
            FenixReviewSettings(settings)
        )
    }

    val torController by lazy { TorController(context) }
}
+76 −3
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.ktx.android.content.res.resolveAttribute
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions
@@ -101,6 +102,8 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.DefaultTopSite
import org.mozilla.fenix.onboarding.FenixOnboarding
import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
import org.mozilla.fenix.tor.TorEvents
import org.mozilla.fenix.tor.bootstrap.TorQuickStart
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.FragmentPreDrawManager
import org.mozilla.fenix.utils.ToolbarPopupWindow
@@ -164,6 +167,7 @@ class HomeFragment : Fragment() {
    private lateinit var currentMode: CurrentMode

    private val topSitesFeature = ViewBoundFeatureWrapper<TopSitesFeature>()
    private val torQuickStart by lazy { TorQuickStart(requireContext()) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
@@ -189,6 +193,9 @@ class HomeFragment : Fragment() {
        currentMode = CurrentMode(
            view.context,
            onboarding,
            torQuickStart,
            !BuildConfig.DISABLE_TOR,
            components.torController,
            browsingModeManager,
            ::dispatchModeChanges
        )
@@ -242,7 +249,10 @@ class HomeFragment : Fragment() {
                registerCollectionStorageObserver = ::registerCollectionStorageObserver,
                showDeleteCollectionPrompt = ::showDeleteCollectionPrompt,
                showTabTray = ::openTabTray,
                handleSwipedItemDeletionCancel = ::handleSwipedItemDeletionCancel
                handleSwipedItemDeletionCancel = ::handleSwipedItemDeletionCancel,
                handleTorBootstrapConnect = ::handleTorBootstrapConnect,
                cancelTorBootstrap = ::cancelTorBootstrap,
                initiateTorBootstrap = ::initiateTorBootstrap
            )
        )

@@ -257,6 +267,9 @@ class HomeFragment : Fragment() {
        updateSessionControlView(view)

        activity.themeManager.applyStatusBarTheme(activity)

        adjustHomeFragmentView(currentMode.getCurrentMode(), view)

        return view
    }

@@ -328,6 +341,44 @@ class HomeFragment : Fragment() {
        }
    }

    private fun adjustHomeFragmentView(mode: Mode, view: View?) {
        if (mode == Mode.Bootstrap) {
            view?.sessionControlRecyclerView?.apply {
                setPadding(0, 0, 0, 0)
                (getLayoutParams() as ViewGroup.MarginLayoutParams).setMargins(0, 0, 0, 0)
            }
            view?.homeAppBar?.apply {
                visibility = View.GONE
            }
            view?.toolbarLayout?.apply {
                visibility = View.GONE
            }
        } else {
            // Keep synchronized with xml layout (somehow).
            view?.sessionControlRecyclerView?.apply {
                setPadding(
                    SESSION_CONTROL_VIEW_PADDING,
                    SESSION_CONTROL_VIEW_PADDING,
                    SESSION_CONTROL_VIEW_PADDING,
                    SESSION_CONTROL_VIEW_PADDING
                )
                // Default margin until it is re-set below (either set immediately or after Layout)
                (getLayoutParams() as ViewGroup.MarginLayoutParams).setMargins(
                    0,
                    0,
                    0,
                    DEFAULT_ONBOARDING_FINISH_MARGIN
                )
            }
            view?.homeAppBar?.apply {
                visibility = View.VISIBLE
            }
            view?.toolbarLayout?.apply {
                visibility = View.VISIBLE
            }
        }
    }

    @Suppress("LongMethod", "ComplexMethod")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
@@ -604,8 +655,12 @@ class HomeFragment : Fragment() {
    }

    private fun dispatchModeChanges(mode: Mode) {
        if (mode != Mode.fromBrowsingMode(browsingModeManager.mode)) {
        homeFragmentStore.dispatch(HomeFragmentAction.ModeChange(mode))

        val localView = view
        adjustHomeFragmentView(mode, view)
        if (localView != null) {
            updateSessionControlView(localView)
        }
    }

@@ -646,6 +701,8 @@ class HomeFragment : Fragment() {
        }
        homeViewModel.layoutManagerState =
            sessionControlView!!.view.layoutManager?.onSaveInstanceState()

        currentMode.unregisterTorListener()
    }

    override fun onResume() {
@@ -973,6 +1030,18 @@ class HomeFragment : Fragment() {
        view?.sessionControlRecyclerView?.adapter?.notifyDataSetChanged()
    }

    private fun handleTorBootstrapConnect() {
        requireComponents.torController.onTorConnecting()
    }

    private fun cancelTorBootstrap() {
        requireComponents.torController.stopTor()
    }

    private fun initiateTorBootstrap(withDebugLogging: Boolean = false) {
        requireComponents.torController.initiateTorBootstrap(lifecycleScope, withDebugLogging)
    }

    companion object {
        const val ALL_NORMAL_TABS = "all_normal"
        const val ALL_PRIVATE_TABS = "all_private"
@@ -987,5 +1056,9 @@ class HomeFragment : Fragment() {
        private const val ANIM_SNACKBAR_DELAY = 100L
        private const val CFR_WIDTH_DIVIDER = 1.7
        private const val CFR_Y_OFFSET = -20

        // Layout
        private const val DEFAULT_ONBOARDING_FINISH_MARGIN = 60
        private const val SESSION_CONTROL_VIEW_PADDING = 16
    }
}
+36 −2
Original line number Diff line number Diff line
@@ -10,6 +10,9 @@ import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.service.fxa.sharing.ShareableAccount
import org.mozilla.fenix.tor.TorController
import org.mozilla.fenix.tor.TorEvents
import org.mozilla.fenix.tor.bootstrap.TorQuickStart
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.ext.components
@@ -22,6 +25,7 @@ sealed class Mode {
    object Normal : Mode()
    object Private : Mode()
    data class Onboarding(val state: OnboardingState) : Mode()
    object Bootstrap : Mode()

    companion object {
        fun fromBrowsingMode(browsingMode: BrowsingMode) = when (browsingMode) {
@@ -43,16 +47,26 @@ sealed class OnboardingState {
    object SignedIn : OnboardingState()
}

@SuppressWarnings("LongParameterList", "TooManyFunctions")
class CurrentMode(
    private val context: Context,
    private val onboarding: FenixOnboarding,
    private val torQuickStart: TorQuickStart,
    private val shouldStartTor: Boolean,
    private val torController: TorController,
    private val browsingModeManager: BrowsingModeManager,
    private val dispatchModeChanges: (mode: Mode) -> Unit
) : AccountObserver {
) : AccountObserver, TorEvents {

    private val accountManager by lazy { context.components.backgroundServices.accountManager }

    fun getCurrentMode() = if (onboarding.userHasBeenOnboarded()) {
    init {
        torController.registerTorListener(this)
    }

    fun getCurrentMode() = if (shouldStartTor && (!torQuickStart.quickStartTor() && !torController.isBootstrapped)) {
        Mode.Bootstrap
    } else if (onboarding.userHasBeenOnboarded()) {
        Mode.fromBrowsingMode(browsingModeManager.mode)
    } else {
        val account = accountManager.authenticatedAccount()
@@ -72,6 +86,26 @@ class CurrentMode(
        dispatchModeChanges(getCurrentMode())
    }

    @SuppressWarnings("EmptyFunctionBlock")
    override fun onTorConnecting() {
    }

    override fun onTorConnected() {
        dispatchModeChanges(getCurrentMode())
    }

    override fun onTorStopped() {
        dispatchModeChanges(getCurrentMode())
    }

    @SuppressWarnings("EmptyFunctionBlock")
    override fun onTorStatusUpdate(entry: String?, status: String?) {
    }

    fun unregisterTorListener() {
        torController.unregisterTorListener(this)
    }

    override fun onAuthenticated(account: OAuthAccount, authType: AuthType) = emitModeChanges()
    override fun onAuthenticationProblems() = emitModeChanges()
    override fun onLoggedOut() = emitModeChanges()
Loading