16900 make navgraph inflation asynchronous (#18889)
* For #16900: implement async navgraph inflation For #16900: removed nav graph from xml For #16900: inflate navGraph programatically For #16900: Made NavGraph inflation asynchronous For #16900: Changed to block with runBlocking For #16900: Refactored blocking call into a function For 16900: NavGraph inflation is now async We now attach the nav graph (or check if its attached) on every nav call ( an extension function for NavController). This is done by checking the value of the job stored in PerfNavController.map which keeps track of the job with the NavController as a Key. If the job hasn't been completed, it will block the main thread until the job is done. The job itself is responsible for attaching the navgraph to the navcontroller (and the inflation of the latter too) For 16900: rebased upstream master For 16900: Rebase on master For #16900: Fixed Async Navgraph navigation per review comments. 1)The Asynchronous method is now found in NavGraphProvider.kt. It creates a job on the IO dispatcher 2)The Job is tracked through a WeakHashMap from Controller --> NavGraph 3)The Coroutine scope doesn't use MainScope() anymore 4)The Coroutine is cancelled if the Activity is destroyed 5)The tests mockk the blockForNavGraphInflation method through the FenixReoboelectricTestApplication instead of calling the mock every setup() For #16900: inflateNavGraphAsync now takes navController For #16900: Pass lifecycleScope to NavGraphProvider For #16900: removed unused mock For #16900: Added linter rules for navigate calls We need linting rules to make sure no one calls the NavController.navigate() methods For #16900: Added TestRule to help abstract the mocks in the code For 16900: Fix linting problems For #16900: Cleaned duplicated code in tests For #16900: cleaned up NavGraphTestRule for finished test For #16900: had to revert an accidentally edited file For #16900: rebased master * For #16900: Review nits for async navgraph This is composed of squash commits, the original messages can be found below: -> DisableNavGraphProviderAssertionRule + kdoc. Use test rule in RobolectricApplication. Fix failing CrashReporterControllerTest Fix blame by -> navigate in tests. This commit was generated by the following commands only: ``` find app/src/test -type f -exec sed -i '' "/import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph/d" {} \; find app/src/test -type f -exec sed -i "" "s/navigateBlockingForAsyncNavGraph/navigate/g" {} \; git checkout app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker ``` Fix various blame This is expected to be squashed into the first commit so, if so, it'd fix the blame. Move test rule to helpers pkg. add missing license header Add import change I missed fix unused imports Replace robolectricTestrunner with test rule. Improve navGraphProvider docs Remove unnecessary rule as defined by robolectric. add clarifying comment to robolectric remove unnecessary space * For #16900: nit fixes for MozillaNavigateCheck and lint fixes 3 squash commits: *Changed violation message and fixed the lint rule for MozillaNavigateCheck *Added suppression to NavController.kt *Fixed detekt violations * For 16900: Fixed failing tests Co-authored-by: Michael Comella <michael.l.comella@gmail.com>
This commit is contained in:
parent
973c891c5e
commit
990bfa7e6d
|
@ -21,7 +21,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule
|
|||
|
||||
// BEFORE INCREASING THESE VALUES, PLEASE CONSULT WITH THE PERF TEAM.
|
||||
private const val EXPECTED_SUPPRESSION_COUNT = 11
|
||||
private const val EXPECTED_RUNBLOCKING_COUNT = 2
|
||||
private const val EXPECTED_RUNBLOCKING_COUNT = 3
|
||||
private const val EXPECTED_COMPONENT_INIT_COUNT = 42
|
||||
private const val EXPECTED_VIEW_HIERARCHY_DEPTH = 12
|
||||
private const val EXPECTED_RECYCLER_VIEW_CONSTRAINT_LAYOUT_CHILDREN = 4
|
||||
|
|
|
@ -15,6 +15,7 @@ import mozilla.components.concept.engine.request.RequestInterceptor
|
|||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.isOnline
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class AppRequestInterceptor(
|
||||
|
@ -97,7 +98,7 @@ class AppRequestInterceptor(
|
|||
|
||||
// Navigate and trigger add-on installation.
|
||||
matchResult.groupValues.getOrNull(1)?.let { addonId ->
|
||||
navController?.get()?.navigate(
|
||||
navController?.get()?.navigateBlockingForAsyncNavGraph(
|
||||
NavGraphDirections.actionGlobalAddonsManagementFragment(addonId)
|
||||
)
|
||||
|
||||
|
|
|
@ -33,12 +33,12 @@ import androidx.navigation.ui.AppBarConfiguration
|
|||
import androidx.navigation.ui.NavigationUI
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import mozilla.appservices.places.BookmarkRoot
|
||||
import mozilla.components.browser.state.action.ContentAction
|
||||
import mozilla.components.browser.state.search.SearchEngine
|
||||
|
@ -79,6 +79,7 @@ import org.mozilla.fenix.exceptions.trackingprotection.TrackingProtectionExcepti
|
|||
import org.mozilla.fenix.ext.alreadyOnDestination
|
||||
import org.mozilla.fenix.ext.breadcrumb
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.measureNoInline
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.nav
|
||||
|
@ -94,6 +95,7 @@ import org.mozilla.fenix.library.bookmarks.BookmarkFragmentDirections
|
|||
import org.mozilla.fenix.library.bookmarks.DesktopFolders
|
||||
import org.mozilla.fenix.library.history.HistoryFragmentDirections
|
||||
import org.mozilla.fenix.library.recentlyclosed.RecentlyClosedFragmentDirections
|
||||
import org.mozilla.fenix.perf.NavGraphProvider
|
||||
import org.mozilla.fenix.perf.Performance
|
||||
import org.mozilla.fenix.perf.PerformanceInflater
|
||||
import org.mozilla.fenix.perf.ProfilerMarkers
|
||||
|
@ -131,7 +133,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
|||
// components requires context to access.
|
||||
protected val homeActivityInitTimeStampNanoSeconds = SystemClock.elapsedRealtimeNanos()
|
||||
|
||||
private var webExtScope: CoroutineScope? = null
|
||||
lateinit var themeManager: ThemeManager
|
||||
lateinit var browsingModeManager: BrowsingModeManager
|
||||
|
||||
|
@ -193,7 +194,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
|||
components.publicSuffixList.prefetch()
|
||||
|
||||
setupThemeAndBrowsingMode(getModeFromIntentOrLastKnown(intent))
|
||||
setContentView(R.layout.activity_home)
|
||||
setContentView(R.layout.activity_home).run {
|
||||
// Do not call anything between setContentView and inflateNavGraphAsync.
|
||||
// It needs to start its job as early as possible.
|
||||
NavGraphProvider.inflateNavGraphAsync(navHost.navController, lifecycleScope)
|
||||
}
|
||||
|
||||
// Must be after we set the content view
|
||||
if (isVisuallyComplete) {
|
||||
|
@ -934,7 +939,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
|||
webExtensionId = webExtensionState.id,
|
||||
webExtensionTitle = webExtensionState.name
|
||||
)
|
||||
navHost.navController.navigate(action)
|
||||
navHost.navController.navigateBlockingForAsyncNavGraph(action)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.navigation.NavController
|
|||
import mozilla.components.feature.addons.Addon
|
||||
import mozilla.components.feature.addons.ui.AddonsManagerAdapterDelegate
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
|
||||
/**
|
||||
|
@ -55,6 +56,6 @@ class AddonsManagementView(
|
|||
AddonsManagementFragmentDirections.actionAddonsManagementFragmentToNotYetSupportedAddonFragment(
|
||||
unsupportedAddons.toTypedArray()
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
|
||||
|
@ -215,7 +216,7 @@ class InstalledAddonDetailsFragment : Fragment() {
|
|||
InstalledAddonDetailsFragmentDirections
|
||||
.actionInstalledAddonFragmentToAddonInternalSettingsFragment(addon)
|
||||
}
|
||||
Navigation.findNavController(this).navigate(directions)
|
||||
Navigation.findNavController(this).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +227,7 @@ class InstalledAddonDetailsFragment : Fragment() {
|
|||
InstalledAddonDetailsFragmentDirections.actionInstalledAddonFragmentToAddonDetailsFragment(
|
||||
addon
|
||||
)
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
Navigation.findNavController(view).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +237,7 @@ class InstalledAddonDetailsFragment : Fragment() {
|
|||
InstalledAddonDetailsFragmentDirections.actionInstalledAddonFragmentToAddonPermissionsDetailsFragment(
|
||||
addon
|
||||
)
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
Navigation.findNavController(view).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ import java.lang.ref.WeakReference
|
|||
import mozilla.components.feature.session.behavior.EngineViewBrowserToolbarBehavior
|
||||
import mozilla.components.feature.webauthn.WebAuthnFeature
|
||||
import mozilla.components.support.base.feature.ActivityResultHandler
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import mozilla.components.support.ktx.android.view.enterToImmersiveMode
|
||||
import org.mozilla.fenix.GleanMetrics.PerfStartup
|
||||
import org.mozilla.fenix.ext.measureNoInline
|
||||
|
@ -557,7 +558,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
|||
showPage = true,
|
||||
sessionId = getCurrentTab()?.id
|
||||
)
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
},
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
|
@ -568,7 +569,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
|||
browserAnimator.captureEngineViewAndDrawStatically {
|
||||
val directions =
|
||||
NavGraphDirections.actionGlobalSavedLoginsAuthFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
),
|
||||
|
@ -979,7 +980,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
|||
}
|
||||
|
||||
override fun onBackLongPressed(): Boolean {
|
||||
findNavController().navigate(
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
NavGraphDirections.actionGlobalTabHistoryDialogFragment(
|
||||
activeSessionId = customTabSessionId
|
||||
)
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.mozilla.fenix.components.FenixSnackbar
|
|||
import org.mozilla.fenix.components.TabCollectionStorage
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
|
@ -264,7 +265,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
)
|
||||
.setText(view.context.getString(messageStringRes))
|
||||
.setAction(requireContext().getString(R.string.create_collection_view)) {
|
||||
findNavController().navigate(
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = false)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.mozilla.fenix.browser.readermode.ReaderModeController
|
|||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.home.HomeScreenViewModel
|
||||
|
@ -118,7 +119,7 @@ class DefaultBrowserToolbarController(
|
|||
// When closing the last tab we must show the undo snackbar in the home fragment
|
||||
if (store.state.getNormalOrPrivateTabs(it.content.private).count() == 1) {
|
||||
homeViewModel.sessionToDelete = it.id
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalHome()
|
||||
)
|
||||
} else {
|
||||
|
@ -132,7 +133,7 @@ class DefaultBrowserToolbarController(
|
|||
Event.TabCounterMenuItemTapped(Event.TabCounterMenuItemTapped.Item.NEW_TAB)
|
||||
)
|
||||
activity.browsingModeManager.mode = BrowsingMode.Normal
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)
|
||||
)
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ class DefaultBrowserToolbarController(
|
|||
)
|
||||
)
|
||||
activity.browsingModeManager.mode = BrowsingMode.Private
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.mozilla.fenix.components.metrics.Event
|
|||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getRootView
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
import org.mozilla.fenix.ext.openSetDefaultBrowserOption
|
||||
|
@ -162,7 +163,7 @@ class DefaultBrowserToolbarMenuController(
|
|||
}
|
||||
is ToolbarMenu.Item.Back -> {
|
||||
if (item.viewHistory) {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(
|
||||
activeSessionId = customTabSessionId
|
||||
)
|
||||
|
@ -175,7 +176,7 @@ class DefaultBrowserToolbarMenuController(
|
|||
}
|
||||
is ToolbarMenu.Item.Forward -> {
|
||||
if (item.viewHistory) {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(
|
||||
activeSessionId = customTabSessionId
|
||||
)
|
||||
|
@ -212,7 +213,7 @@ class DefaultBrowserToolbarMenuController(
|
|||
),
|
||||
showPage = true
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
is ToolbarMenu.Item.Settings -> browserAnimator.captureEngineViewAndDrawStatically {
|
||||
val directions = BrowserFragmentDirections.actionBrowserFragmentToSettingsFragment()
|
||||
|
@ -341,7 +342,7 @@ class DefaultBrowserToolbarMenuController(
|
|||
)
|
||||
}
|
||||
is ToolbarMenu.Item.NewTab -> {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
BrowserFragmentDirections.actionGlobalHome(focusOnAddressBar = true)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// We suppress the calls to `navigate` since we invoke the Android `NavController.navigate` through
|
||||
// this file. Detekt checks for the `navigate()` function calls, which should be ignored in this file.
|
||||
@file:Suppress("MozillaNavigateCheck")
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
|
@ -10,12 +13,15 @@ import androidx.navigation.NavDirections
|
|||
import androidx.navigation.NavOptions
|
||||
import io.sentry.Sentry
|
||||
import org.mozilla.fenix.components.isSentryEnabled
|
||||
import org.mozilla.fenix.perf.NavGraphProvider
|
||||
|
||||
/**
|
||||
* Navigate from the fragment with [id] using the given [directions].
|
||||
* If the id doesn't match the current destination, an error is recorded.
|
||||
*/
|
||||
fun NavController.nav(@IdRes id: Int?, directions: NavDirections, navOptions: NavOptions? = null) {
|
||||
NavGraphProvider.blockForNavGraphInflation(this)
|
||||
|
||||
if (id == null || this.currentDestination?.id == id) {
|
||||
this.navigate(directions, navOptions)
|
||||
} else {
|
||||
|
@ -23,6 +29,21 @@ fun NavController.nav(@IdRes id: Int?, directions: NavDirections, navOptions: Na
|
|||
}
|
||||
}
|
||||
|
||||
fun NavController.navigateBlockingForAsyncNavGraph(resId: Int) {
|
||||
NavGraphProvider.blockForNavGraphInflation(this)
|
||||
this.navigate(resId)
|
||||
}
|
||||
|
||||
fun NavController.navigateBlockingForAsyncNavGraph(directions: NavDirections) {
|
||||
NavGraphProvider.blockForNavGraphInflation(this)
|
||||
this.navigate(directions)
|
||||
}
|
||||
|
||||
fun NavController.navigateBlockingForAsyncNavGraph(directions: NavDirections, navOptions: NavOptions?) {
|
||||
NavGraphProvider.blockForNavGraphInflation(this)
|
||||
this.navigate(directions, navOptions)
|
||||
}
|
||||
|
||||
fun NavController.alreadyOnDestination(@IdRes destId: Int?): Boolean {
|
||||
return destId?.let { currentDestination?.id == it || popBackStack(it, false) } ?: false
|
||||
}
|
||||
|
@ -38,6 +59,6 @@ fun NavController.navigateSafe(
|
|||
directions: NavDirections
|
||||
) {
|
||||
if (currentDestination?.id == resId) {
|
||||
this.navigate(directions)
|
||||
this.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ import org.mozilla.fenix.components.toolbar.FenixTabCounterMenu
|
|||
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.hideToolbar
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.measureNoInline
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.nav
|
||||
|
@ -533,7 +534,7 @@ class HomeFragment : Fragment() {
|
|||
requireContext().getString(R.string.snackbar_deleted_undo),
|
||||
{
|
||||
requireComponents.useCases.tabsUseCases.undo.invoke()
|
||||
findNavController().navigate(
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
HomeFragmentDirections.actionGlobalBrowser(null)
|
||||
)
|
||||
},
|
||||
|
@ -624,7 +625,8 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navToSavedLogins() {
|
||||
findNavController().navigate(HomeFragmentDirections.actionGlobalSavedLoginsAuthFragment())
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
HomeFragmentDirections.actionGlobalSavedLoginsAuthFragment())
|
||||
}
|
||||
|
||||
private fun dispatchModeChanges(mode: Mode) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.content.Intent
|
|||
import androidx.navigation.NavController
|
||||
import mozilla.components.lib.crash.Crash
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
|
||||
/**
|
||||
* When the app crashes, the user has the option to report it.
|
||||
|
@ -26,6 +27,6 @@ class CrashReporterIntentProcessor : HomeIntentProcessor {
|
|||
|
||||
private fun openToCrashReporter(intent: Intent, navController: NavController) {
|
||||
val directions = NavGraphDirections.actionGlobalCrashReporter(intent)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.components.SearchWidgetCreator
|
||||
import org.mozilla.fenix.ext.alreadyOnDestination
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.home.intent.DeepLinkIntentProcessor.DeepLinkVerifier
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
|
||||
|
@ -76,7 +77,7 @@ class DeepLinkIntentProcessor(
|
|||
}
|
||||
|
||||
if (!navController.alreadyOnDestination(globalDirections.destinationId)) {
|
||||
navController.navigate(globalDirections.navDirections)
|
||||
navController.navigateBlockingForAsyncNavGraph(globalDirections.navDirections)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import kotlinx.android.synthetic.main.onboarding_manual_signin.view.*
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
|
||||
class OnboardingManualSignInViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
|
@ -22,7 +23,7 @@ class OnboardingManualSignInViewHolder(view: View) : RecyclerView.ViewHolder(vie
|
|||
it.context.components.analytics.metrics.track(Event.OnboardingManualSignIn)
|
||||
|
||||
val directions = HomeFragmentDirections.actionGlobalTurnOnSync()
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
Navigation.findNavController(view).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ class DefaultBookmarkController(
|
|||
}
|
||||
|
||||
override fun handleBookmarkEdit(node: BookmarkNode) {
|
||||
navigate(BookmarkFragmentDirections.actionBookmarkFragmentToBookmarkEditFragment(node.guid))
|
||||
navigateToGivenDirection(BookmarkFragmentDirections.actionBookmarkFragmentToBookmarkEditFragment(node.guid))
|
||||
}
|
||||
|
||||
override fun handleBookmarkSelected(node: BookmarkNode) {
|
||||
|
@ -118,7 +118,7 @@ class DefaultBookmarkController(
|
|||
}
|
||||
|
||||
override fun handleBookmarkSharing(item: BookmarkNode) {
|
||||
navigate(
|
||||
navigateToGivenDirection(
|
||||
BookmarkFragmentDirections.actionGlobalShareFragment(
|
||||
data = arrayOf(ShareData(url = item.url, title = item.title))
|
||||
)
|
||||
|
@ -182,7 +182,7 @@ class DefaultBookmarkController(
|
|||
}
|
||||
}
|
||||
|
||||
private fun navigate(directions: NavDirections) {
|
||||
private fun navigateToGivenDirection(directions: NavDirections) {
|
||||
invokePendingDeletion.invoke()
|
||||
navController.nav(R.id.bookmarkFragment, directions)
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
|
|||
true
|
||||
}
|
||||
R.id.add_bookmark_folder -> {
|
||||
navigate(
|
||||
navigateToBookmarkFragment(
|
||||
BookmarkFragmentDirections
|
||||
.actionBookmarkFragmentToBookmarkAddFolderFragment()
|
||||
)
|
||||
|
@ -226,7 +226,7 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
|
|||
val shareTabs = bookmarkStore.state.mode.selectedItems.map {
|
||||
ShareData(url = it.url, title = it.title)
|
||||
}
|
||||
navigate(
|
||||
navigateToBookmarkFragment(
|
||||
BookmarkFragmentDirections.actionGlobalShareFragment(
|
||||
data = shareTabs.toTypedArray()
|
||||
)
|
||||
|
@ -243,10 +243,10 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
|
|||
|
||||
private fun showTabTray() {
|
||||
invokePendingDeletion()
|
||||
navigate(BookmarkFragmentDirections.actionGlobalTabTrayDialogFragment())
|
||||
navigateToBookmarkFragment(BookmarkFragmentDirections.actionGlobalTabTrayDialogFragment())
|
||||
}
|
||||
|
||||
private fun navigate(directions: NavDirections) {
|
||||
private fun navigateToBookmarkFragment(directions: NavDirections) {
|
||||
invokePendingDeletion()
|
||||
findNavController().nav(
|
||||
R.id.bookmarkFragment,
|
||||
|
|
|
@ -15,6 +15,7 @@ import mozilla.components.concept.storage.BookmarkNode
|
|||
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.library.LibraryPageView
|
||||
import org.mozilla.fenix.selection.SelectionInteractor
|
||||
|
||||
|
@ -119,7 +120,7 @@ class BookmarkView(
|
|||
adapter = bookmarkAdapter
|
||||
}
|
||||
view.bookmark_folders_sign_in.setOnClickListener {
|
||||
navController.navigate(NavGraphDirections.actionGlobalTurnOnSync())
|
||||
navController.navigateBlockingForAsyncNavGraph(NavGraphDirections.actionGlobalTurnOnSync())
|
||||
}
|
||||
view.swipe_refresh.setOnRefreshListener {
|
||||
interactor.onRequestSync()
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
|||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
interface HistoryController {
|
||||
|
@ -94,7 +95,7 @@ class DefaultHistoryController(
|
|||
}
|
||||
|
||||
override fun handleShare(item: HistoryItem) {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
HistoryFragmentDirections.actionGlobalShareFragment(
|
||||
data = arrayOf(ShareData(url = item.url, title = item.title))
|
||||
)
|
||||
|
@ -110,7 +111,7 @@ class DefaultHistoryController(
|
|||
}
|
||||
|
||||
override fun handleEnterRecentlyClosed() {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
HistoryFragmentDirections.actionGlobalRecentlyClosed(),
|
||||
NavOptions.Builder().setPopUpTo(R.id.recentlyClosedFragment, true).build()
|
||||
)
|
||||
|
|
|
@ -304,10 +304,10 @@ class HistoryFragment : LibraryPageFragment<HistoryItem>(), UserInteractionHandl
|
|||
val directions = HistoryFragmentDirections.actionGlobalShareFragment(
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navigate(directions)
|
||||
navigateToHistoryFragment(directions)
|
||||
}
|
||||
|
||||
private fun navigate(directions: NavDirections) {
|
||||
private fun navigateToHistoryFragment(directions: NavDirections) {
|
||||
invokePendingDeletion()
|
||||
findNavController().nav(
|
||||
R.id.historyFragment,
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
|
||||
interface RecentlyClosedController {
|
||||
fun handleOpen(item: RecoverableTab, mode: BrowsingMode? = null)
|
||||
|
@ -48,7 +49,7 @@ class DefaultRecentlyClosedController(
|
|||
}
|
||||
|
||||
override fun handleNavigateToHistory() {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
RecentlyClosedFragmentDirections.actionGlobalHistoryFragment(),
|
||||
NavOptions.Builder().setPopUpTo(R.id.historyFragment, true).build()
|
||||
)
|
||||
|
@ -64,7 +65,7 @@ class DefaultRecentlyClosedController(
|
|||
}
|
||||
|
||||
override fun handleShare(item: RecoverableTab) {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
RecentlyClosedFragmentDirections.actionGlobalShareFragment(
|
||||
data = arrayOf(ShareData(url = item.url, title = item.title))
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix.nimbus
|
|||
import androidx.navigation.NavController
|
||||
import mozilla.components.service.nimbus.ui.NimbusExperimentsAdapterDelegate
|
||||
import org.mozilla.experiments.nimbus.EnrolledExperiment
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
|
||||
/**
|
||||
* View used for managing Nimbus experiments.
|
||||
|
@ -21,6 +22,6 @@ class NimbusExperimentsView(
|
|||
experiment.userFacingName
|
||||
)
|
||||
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.perf
|
||||
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.navigation.NavController
|
||||
import java.util.WeakHashMap
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
/**
|
||||
* This class asynchronously loads the navigation graph XML. This is a performance optimization:
|
||||
* large nav graphs take ~29ms to inflate on the Moto G5 (#16900). This also seemingly prevents the
|
||||
* HomeFragment layout XML from being unnecessarily inflated when it isn't used, improving perf by
|
||||
* ~148ms on the Moto G5 for VIEW start up (#18245) though it was unintentional and we may wish to
|
||||
* implement more intentional for that.
|
||||
*
|
||||
* This class is defined as an Object, rather than as a class instance in our Components, because
|
||||
* it needs to be called by the [NavController] extension function which can't easily access Components.
|
||||
*
|
||||
* To use this class properly, [inflateNavGraphAsync] must be called first before
|
||||
* [blockForNavGraphInflation] using the same [NavController] instance.
|
||||
*/
|
||||
object NavGraphProvider {
|
||||
|
||||
// We want to store member state on the NavController. However, there is no way to do this.
|
||||
// Instead, we store state as part of a map: NavController instance -> State. In order to
|
||||
// garbage collect our data when the NavController is no longer relevant, we use a WeakHashMap.
|
||||
private val map = WeakHashMap<NavController, Job>()
|
||||
|
||||
fun inflateNavGraphAsync(navController: NavController, lifecycleScope: LifecycleCoroutineScope) {
|
||||
val inflationJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
val inflater = navController.navInflater
|
||||
navController.graph = inflater.inflate(R.navigation.nav_graph)
|
||||
}
|
||||
|
||||
map[navController] = inflationJob
|
||||
}
|
||||
|
||||
/**
|
||||
* The job should block the main thread if it isn't completed so that the NavGraph can be loaded
|
||||
* before any navigation is done.
|
||||
*
|
||||
* [inflateNavGraphAsync] must be called before this method.
|
||||
*
|
||||
* @throws IllegalStateException if [inflateNavGraphAsync] wasn't called first for this [NavController]
|
||||
*/
|
||||
fun blockForNavGraphInflation(navController: NavController) {
|
||||
val inflationJob = map[navController] ?: throw IllegalStateException("Expected " +
|
||||
"`NavGraphProvider.inflateNavGraphAsync` to be called before this method with the same " +
|
||||
"`NavController` instance. If this occurred in a test, you probably need to add the " +
|
||||
"DisableNavGraphProviderAssertionRule.")
|
||||
runBlockingIncrement { inflationJob.join() }
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ import org.mozilla.fenix.components.metrics.Event
|
|||
import org.mozilla.fenix.ext.application
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.navigateToNotificationsSettings
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
|
@ -480,7 +481,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private fun navigateFromSettings(directions: NavDirections) {
|
||||
view?.findNavController()?.let { navController ->
|
||||
if (navController.currentDestination?.id == R.id.settingsFragment) {
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
@ -32,7 +33,7 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
|||
private val exceptionsClickListener = Preference.OnPreferenceClickListener {
|
||||
val directions =
|
||||
TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
|
||||
requireView().findNavController().navigate(directions)
|
||||
requireView().findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
true
|
||||
}
|
||||
private lateinit var customCookies: CheckBoxPreference
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.crashes.CrashListActivity
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
|
@ -178,7 +179,7 @@ class AboutFragment : Fragment(), AboutPageListener {
|
|||
|
||||
private fun openLibrariesPage() {
|
||||
val navController = findNavController()
|
||||
navController.navigate(R.id.action_aboutFragment_to_aboutLibrariesFragment)
|
||||
navController.navigateBlockingForAsyncNavGraph(R.id.action_aboutFragment_to_aboutLibrariesFragment)
|
||||
}
|
||||
|
||||
override fun onAboutItemClicked(item: AboutItem) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
|
@ -59,7 +60,7 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
|||
|
||||
private fun navigateToPairFragment() {
|
||||
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairFragment()
|
||||
requireView().findNavController().navigate(directions)
|
||||
requireView().findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
requireComponents.analytics.metrics.track(Event.SyncAuthScanPairing)
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.preference.PreferenceFragmentCompat
|
|||
import mozilla.components.service.fxa.SyncEngine
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.settings.SyncPreferenceView
|
||||
|
@ -39,17 +40,17 @@ class CreditCardsSettingFragment : PreferenceFragmentCompat() {
|
|||
onSignInToSyncClicked = {
|
||||
val directions =
|
||||
CreditCardsSettingFragmentDirections.actionCreditCardsSettingFragmentToTurnOnSyncFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
},
|
||||
onSyncStatusClicked = {
|
||||
val directions =
|
||||
CreditCardsSettingFragmentDirections.actionGlobalAccountSettingsFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
},
|
||||
onReconnectClicked = {
|
||||
val directions =
|
||||
CreditCardsSettingFragmentDirections.actionGlobalAccountProblemFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -61,13 +62,13 @@ class CreditCardsSettingFragment : PreferenceFragmentCompat() {
|
|||
val directions =
|
||||
CreditCardsSettingFragmentDirections
|
||||
.actionCreditCardsSettingFragmentToCreditCardEditorFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
getPreferenceKey(R.string.pref_key_credit_cards_manage_saved_cards) -> {
|
||||
val directions =
|
||||
CreditCardsSettingFragmentDirections
|
||||
.actionCreditCardsSettingFragmentToCreditCardsManagementFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.settings.creditcards.controller
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.settings.creditcards.CreditCardsManagementFragmentDirections
|
||||
|
||||
/**
|
||||
|
@ -27,7 +28,7 @@ class DefaultCreditCardsManagementController(
|
|||
) : CreditCardsManagementController {
|
||||
|
||||
override fun handleCreditCardClicked() {
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
CreditCardsManagementFragmentDirections
|
||||
.actionCreditCardsManagementFragmentToCreditCardEditorFragment()
|
||||
)
|
||||
|
|
|
@ -28,6 +28,7 @@ import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
|
@ -199,7 +200,7 @@ class DeleteBrowsingDataFragment : Fragment(R.layout.fragment_delete_browsing_da
|
|||
// If the user deletes all open tabs we need to make sure we remove
|
||||
// the BrowserFragment from the backstack.
|
||||
popBackStack(R.id.homeFragment, false)
|
||||
navigate(DeleteBrowsingDataFragmentDirections.actionGlobalSettingsFragment())
|
||||
navigateBlockingForAsyncNavGraph(DeleteBrowsingDataFragmentDirections.actionGlobalSettingsFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.navigation.NavController
|
|||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
import org.mozilla.fenix.settings.logins.LoginsAction
|
||||
import org.mozilla.fenix.settings.logins.LoginsFragmentStore
|
||||
|
@ -40,7 +41,7 @@ class LoginsListController(
|
|||
fun handleItemClicked(item: SavedLogin) {
|
||||
loginsFragmentStore.dispatch(LoginsAction.LoginSelected(item))
|
||||
metrics.track(Event.OpenOneLogin)
|
||||
navController.navigate(
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
SavedLoginsFragmentDirections.actionSavedLoginsFragmentToLoginDetailFragment(item.guid)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import mozilla.components.service.sync.logins.LoginsStorageException
|
|||
import mozilla.components.service.sync.logins.NoSuchRecordException
|
||||
import mozilla.components.service.sync.logins.SyncableLoginsStorage
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.settings.logins.LoginsAction
|
||||
import org.mozilla.fenix.settings.logins.LoginsFragmentStore
|
||||
import org.mozilla.fenix.settings.logins.fragment.EditLoginFragmentDirections
|
||||
|
@ -83,7 +84,7 @@ open class SavedLoginsStorageController(
|
|||
EditLoginFragmentDirections.actionEditLoginFragmentToLoginDetailFragment(
|
||||
loginId
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
saveLoginJob?.invokeOnCompletion {
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.mozilla.fenix.components.StoreProvider
|
|||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.increaseTapArea
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.redirectToReAuth
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
@ -199,7 +200,7 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) {
|
|||
LoginDetailFragmentDirections.actionLoginDetailFragmentToEditLoginFragment(
|
||||
login!!
|
||||
)
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
private fun displayDeleteLoginDialog() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.ext.secure
|
||||
|
@ -130,17 +131,17 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() {
|
|||
onSignInToSyncClicked = {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
},
|
||||
onSyncStatusClicked = {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountSettingsFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
},
|
||||
onReconnectClicked = {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountProblemFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -213,19 +214,19 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() {
|
|||
context?.components?.analytics?.metrics?.track(Event.OpenLogins)
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToLoginsListFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
private fun navigateToSaveLoginSettingFragment() {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToSavedLoginsSettingFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
private fun navigateToLoginExceptionFragment() {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToLoginExceptionsFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -18,6 +18,7 @@ import mozilla.components.feature.sitepermissions.SitePermissions
|
|||
import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase
|
||||
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
|
||||
import org.mozilla.fenix.components.PermissionStorage
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.toggle
|
||||
|
@ -199,6 +200,6 @@ class DefaultQuickSettingsController(
|
|||
private fun navigateToManagePhoneFeature(phoneFeature: PhoneFeature) {
|
||||
val directions = QuickSettingsSheetDialogFragmentDirections
|
||||
.actionGlobalSitePermissionsManagePhoneFeature(phoneFeature)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getRootView
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.utils.allowUndo
|
||||
|
||||
class RadioSearchEngineListPreference @JvmOverloads constructor(
|
||||
|
@ -146,7 +147,7 @@ class RadioSearchEngineListPreference @JvmOverloads constructor(
|
|||
val directions = SearchEngineFragmentDirections
|
||||
.actionSearchEngineFragmentToEditCustomSearchEngineFragment(engine.id)
|
||||
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
Navigation.findNavController(view).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
private fun deleteSearchEngine(
|
||||
|
|
|
@ -13,6 +13,7 @@ import androidx.preference.SwitchPreference
|
|||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
import org.mozilla.fenix.settings.SharedPreferenceUpdater
|
||||
|
@ -99,7 +100,7 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
|
|||
getPreferenceKey(R.string.pref_key_add_search_engine) -> {
|
||||
val directions = SearchEngineFragmentDirections
|
||||
.actionSearchEngineFragmentToAddSearchEngineFragment()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.withContext
|
|||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
|
@ -161,6 +162,6 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() {
|
|||
phoneFeature = phoneFeature,
|
||||
sitePermissions = sitePermissions
|
||||
)
|
||||
requireView().findNavController().navigate(directions)
|
||||
requireView().findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.preference.PreferenceFragmentCompat
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
|
@ -42,7 +43,7 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
exceptionsCategory.onPreferenceClickListener = OnPreferenceClickListener {
|
||||
val directions = SitePermissionsFragmentDirections.actionSitePermissionsToExceptions()
|
||||
Navigation.findNavController(requireView()).navigate(directions)
|
||||
Navigation.findNavController(requireView()).navigateBlockingForAsyncNavGraph(directions)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +77,6 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
|||
requireComponents.analytics.metrics.track(Event.AutoPlaySettingVisited)
|
||||
}
|
||||
|
||||
Navigation.findNavController(requireView()).navigate(directions)
|
||||
Navigation.findNavController(requireView()).navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import mozilla.components.support.ktx.kotlin.isExtensionUrl
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.share.listadapters.AppShareOption
|
||||
|
@ -121,7 +122,7 @@ class DefaultShareController(
|
|||
|
||||
override fun handleAddNewDevice() {
|
||||
val directions = ShareFragmentDirections.actionShareFragmentToAddNewDeviceFragment()
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
override fun handleShareToDevice(device: Device) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import mozilla.components.concept.sync.DeviceType
|
|||
import mozilla.components.feature.syncedtabs.view.SyncedTabsView
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.sync.SyncedTabsAdapter.AdapterItem
|
||||
|
||||
/**
|
||||
|
@ -63,7 +64,7 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item
|
|||
errorItem.navController?.let { navController ->
|
||||
itemView.sync_tabs_error_cta_button.visibility = VISIBLE
|
||||
itemView.sync_tabs_error_cta_button.setOnClickListener {
|
||||
navController.navigate(NavGraphDirections.actionGlobalTurnOnSync())
|
||||
navController.navigateBlockingForAsyncNavGraph(NavGraphDirections.actionGlobalTurnOnSync())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.mozilla.fenix.components.TabCollectionStorage
|
|||
import org.mozilla.fenix.components.bookmarks.BookmarksUseCase
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
import org.mozilla.fenix.tabstray.ext.getTabSessionState
|
||||
|
||||
|
@ -91,11 +92,13 @@ class DefaultNavigationInteractor(
|
|||
}
|
||||
|
||||
override fun onTabSettingsClicked() {
|
||||
navController.navigate(TabsTrayFragmentDirections.actionGlobalTabSettingsFragment())
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
TabsTrayFragmentDirections.actionGlobalTabSettingsFragment())
|
||||
}
|
||||
|
||||
override fun onOpenRecentlyClosedClicked() {
|
||||
navController.navigate(TabsTrayFragmentDirections.actionGlobalRecentlyClosed())
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
TabsTrayFragmentDirections.actionGlobalRecentlyClosed())
|
||||
metrics.track(Event.RecentlyClosedTabsOpened)
|
||||
}
|
||||
|
||||
|
@ -106,7 +109,7 @@ class DefaultNavigationInteractor(
|
|||
val directions = TabsTrayFragmentDirections.actionGlobalShareFragment(
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
override fun onShareTabsOfTypeClicked(private: Boolean) {
|
||||
|
@ -117,7 +120,7 @@ class DefaultNavigationInteractor(
|
|||
val directions = TabsTrayFragmentDirections.actionGlobalShareFragment(
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
|||
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.tabtray.TabTrayDialogFragmentDirections
|
||||
|
||||
interface TabsTrayController {
|
||||
|
@ -43,7 +44,8 @@ class DefaultTabsTrayController(
|
|||
override fun onNewTabTapped(isPrivate: Boolean) {
|
||||
val startTime = profiler?.getProfilerTime()
|
||||
browsingModeManager.mode = BrowsingMode.fromBoolean(isPrivate)
|
||||
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
||||
navigationInteractor.onTabTrayDismissed()
|
||||
profiler?.addMarker(
|
||||
"DefaultTabTrayController.onNewTabTapped",
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.mozilla.fenix.NavGraphDirections
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.StoreProvider
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.home.HomeScreenViewModel
|
||||
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
|
||||
|
@ -241,7 +242,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor {
|
|||
}
|
||||
|
||||
if (!navController.popBackStack(R.id.browserFragment, false)) {
|
||||
navController.navigate(R.id.browserFragment)
|
||||
navController.navigateBlockingForAsyncNavGraph(R.id.browserFragment)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,7 +302,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor {
|
|||
private fun dismissTabTrayAndNavigateHome(sessionId: String) {
|
||||
homeViewModel.sessionToDelete = sessionId
|
||||
val directions = NavGraphDirections.actionGlobalHome()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
|
|||
import org.mozilla.fenix.components.TabCollectionStorage
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
|
||||
/**
|
||||
|
@ -104,7 +105,8 @@ class DefaultTabTrayController(
|
|||
override fun handleNewTabTapped(private: Boolean) {
|
||||
val startTime = profiler?.getProfilerTime()
|
||||
browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
||||
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
||||
dismissTabTray()
|
||||
profiler?.addMarker(
|
||||
"DefaultTabTrayController.onNewTabTapped",
|
||||
|
@ -113,7 +115,8 @@ class DefaultTabTrayController(
|
|||
}
|
||||
|
||||
override fun handleTabSettingsClicked() {
|
||||
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalTabSettingsFragment())
|
||||
navController.navigateBlockingForAsyncNavGraph(
|
||||
TabTrayDialogFragmentDirections.actionGlobalTabSettingsFragment())
|
||||
}
|
||||
|
||||
override fun handleTabTrayDismissed() {
|
||||
|
@ -148,7 +151,7 @@ class DefaultTabTrayController(
|
|||
val directions = TabTrayDialogFragmentDirections.actionGlobalShareFragment(
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
override fun handleShareSelectedTabsClicked(selectedTabs: Set<Tab>) {
|
||||
|
@ -158,7 +161,7 @@ class DefaultTabTrayController(
|
|||
val directions = TabTrayDialogFragmentDirections.actionGlobalShareFragment(
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
}
|
||||
|
||||
override fun handleBookmarkSelectedTabs(selectedTabs: Set<Tab>) {
|
||||
|
@ -236,13 +239,13 @@ class DefaultTabTrayController(
|
|||
|
||||
override fun handleRecentlyClosedClicked() {
|
||||
val directions = TabTrayDialogFragmentDirections.actionGlobalRecentlyClosed()
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
metrics.track(Event.RecentlyClosedTabsOpened)
|
||||
}
|
||||
|
||||
override fun handleGoToTabsSettingClicked() {
|
||||
val directions = TabTrayDialogFragmentDirections.actionGlobalTabSettingsFragment()
|
||||
navController.navigate(directions)
|
||||
navController.navigateBlockingForAsyncNavGraph(directions)
|
||||
metrics.track(Event.TabsTrayCfrTapped)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.mozilla.fenix.components.TabCollectionStorage
|
|||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getDefaultCollectionNumber
|
||||
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
@ -331,7 +332,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
|
|||
private fun dismissTabTrayAndNavigateHome(sessionId: String) {
|
||||
homeViewModel.sessionToDelete = sessionId
|
||||
val directions = NavGraphDirections.actionGlobalHome()
|
||||
findNavController().navigate(directions)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(directions)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
|
@ -344,7 +345,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
|
|||
dismissAllowingStateLoss()
|
||||
if (findNavController().currentDestination?.id == R.id.browserFragment) return
|
||||
if (!findNavController().popBackStack(R.id.browserFragment, false)) {
|
||||
findNavController().navigate(R.id.browserFragment)
|
||||
findNavController().navigateBlockingForAsyncNavGraph(R.id.browserFragment)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,7 +380,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
|
|||
.setText(requireContext().getString(messageStringRes))
|
||||
.setAction(requireContext().getString(R.string.create_collection_view)) {
|
||||
dismissAllowingStateLoss()
|
||||
findNavController().navigate(
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
TabTrayDialogFragmentDirections.actionGlobalHome(
|
||||
focusOnAddressBar = false,
|
||||
focusOnCollection = collectionToSelect ?: -1L
|
||||
|
@ -403,7 +404,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
|
|||
.setText(requireContext().getString(R.string.snackbar_message_bookmarks_saved))
|
||||
.setAction(requireContext().getString(R.string.snackbar_message_bookmarks_view)) {
|
||||
dismissAllowingStateLoss()
|
||||
findNavController().navigate(
|
||||
findNavController().navigateBlockingForAsyncNavGraph(
|
||||
TabTrayDialogFragmentDirections.actionGlobalBookmarkFragment(BookmarkRoot.Mobile.id)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp" />
|
||||
|
||||
<!--The navGraph is set dynamically in NavGraphProvider -->
|
||||
<fragment
|
||||
android:id="@+id/container"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
app:defaultNavHost="true"/>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -12,14 +12,20 @@ import io.mockk.verify
|
|||
import mozilla.components.lib.crash.Crash
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.Components
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class CrashReporterControllerTest {
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
private lateinit var components: Components
|
||||
private lateinit var crash: Crash
|
||||
private lateinit var sessionId: String
|
||||
|
|
|
@ -18,11 +18,16 @@ import io.mockk.mockkStatic
|
|||
import io.mockk.verify
|
||||
import io.sentry.Sentry
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.components.isSentryEnabled
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
|
||||
class NavControllerTest {
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
private val currentDestId = 4
|
||||
@MockK(relaxUnitFun = true) private lateinit var navController: NavController
|
||||
@MockK private lateinit var navDirections: NavDirections
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.helpers
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkObject
|
||||
import org.junit.rules.TestWatcher
|
||||
import org.junit.runner.Description
|
||||
import org.mozilla.fenix.perf.NavGraphProvider
|
||||
|
||||
/**
|
||||
* Disables the call order assertions defined by the [NavGraphProvider] for use in testing.
|
||||
* This is necessary because unit tests generally don't follow the application lifecycle and thus
|
||||
* call the methods out of order, causing an assertion to be thrown unexpectedly. You may need to
|
||||
* apply this rule if you see the following exception in your test:
|
||||
*
|
||||
* Unfortunately, JUnit 4 discourages setting test state globally so we apply this to each test that
|
||||
* has the failure rather than disabling it globally.
|
||||
*/
|
||||
class DisableNavGraphProviderAssertionRule : TestWatcher() {
|
||||
|
||||
// public for code reuse.
|
||||
fun setUp() {
|
||||
mockkObject(NavGraphProvider)
|
||||
every { NavGraphProvider.blockForNavGraphInflation(any()) } returns Unit
|
||||
}
|
||||
|
||||
// public for code reuse.
|
||||
fun tearDown() { //
|
||||
unmockkObject(NavGraphProvider)
|
||||
}
|
||||
|
||||
override fun starting(description: Description?) {
|
||||
setUp()
|
||||
}
|
||||
|
||||
override fun finished(description: Description?) {
|
||||
tearDown()
|
||||
}
|
||||
}
|
|
@ -7,13 +7,19 @@ package org.mozilla.fenix.helpers
|
|||
import org.mozilla.fenix.FenixApplication
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.TestComponents
|
||||
import org.robolectric.TestLifecycleApplication
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* An override of our application for use in Robolectric-based unit tests. We're forced to override
|
||||
* because our standard application fails to initialize in Robolectric with exceptions like:
|
||||
* "Crash handler service must run in a separate process".
|
||||
*/
|
||||
class FenixRobolectricTestApplication : FenixApplication() {
|
||||
class FenixRobolectricTestApplication : FenixApplication(), TestLifecycleApplication {
|
||||
|
||||
// Though JUnit 4 discourages global rules, we can apply global rules in robolectric so we do
|
||||
// to prevent confusion from devs.
|
||||
private val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
@ -37,4 +43,19 @@ class FenixRobolectricTestApplication : FenixApplication() {
|
|||
// https://github.com/mozilla-mobile/fenix/pull/15646#issuecomment-709411141
|
||||
setTheme(R.style.NormalTheme)
|
||||
}
|
||||
|
||||
// Before test runs before the test class is initialized
|
||||
override fun beforeTest(method: Method?) {}
|
||||
|
||||
// Prepare test runs once the test class and all its member variables (mock and
|
||||
// non mocks) are initialized. This method runs after application.onCreate
|
||||
override fun prepareTest(test: Any?) {
|
||||
// We call this in prepareTest rather than beforeTest because member vars
|
||||
// are initialized so it feels more correct to call it here.
|
||||
disableNavGraphProviderAssertionRule.setUp()
|
||||
}
|
||||
|
||||
override fun afterTest(method: Method?) {
|
||||
disableNavGraphProviderAssertionRule.tearDown()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.Analytics
|
||||
import org.mozilla.fenix.components.TabCollectionStorage
|
||||
|
@ -113,6 +114,9 @@ class DefaultSessionControlControllerTest {
|
|||
private lateinit var store: BrowserStore
|
||||
private lateinit var controller: DefaultSessionControlController
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
store = BrowserStore(
|
||||
|
|
|
@ -30,9 +30,11 @@ import mozilla.components.concept.storage.BookmarkNodeType
|
|||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.components.Services
|
||||
|
@ -87,6 +89,9 @@ class BookmarkControllerTest {
|
|||
BookmarkNodeType.FOLDER, BookmarkRoot.Root.id, null, 0, BookmarkRoot.Root.name, null, null
|
||||
)
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
every { homeActivity.components.services } returns services
|
||||
|
|
|
@ -26,13 +26,16 @@ import mozilla.components.browser.state.store.BrowserStore
|
|||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.components.metrics.MetricsUtils
|
||||
|
||||
import org.mozilla.fenix.search.SearchDialogFragmentDirections.Companion.actionGlobalAddonsManagementFragment
|
||||
import org.mozilla.fenix.search.SearchDialogFragmentDirections.Companion.actionGlobalSearchEngineFragment
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
|
@ -55,13 +58,14 @@ class SearchDialogControllerTest {
|
|||
|
||||
private lateinit var controller: SearchDialogController
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
mockkObject(MetricsUtils)
|
||||
|
||||
val browserStore = BrowserStore()
|
||||
|
||||
every { store.state.tabId } returns "test-tab-id"
|
||||
every { store.state.searchEngineSource.searchEngine } returns searchEngine
|
||||
every { sessionManager.select(any()) } just Runs
|
||||
|
|
|
@ -13,11 +13,16 @@ import io.mockk.verify
|
|||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
class AccountSettingsInteractorTest {
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Test
|
||||
fun onSyncNow() {
|
||||
var ranSyncNow = false
|
||||
|
|
|
@ -9,8 +9,10 @@ import io.mockk.mockk
|
|||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardsManagementController
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
|
||||
class DefaultCreditCardsManagementControllerTest {
|
||||
|
||||
|
@ -18,6 +20,9 @@ class DefaultCreditCardsManagementControllerTest {
|
|||
|
||||
private lateinit var controller: DefaultCreditCardsManagementController
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
controller = spyk(
|
||||
|
|
|
@ -20,10 +20,12 @@ import mozilla.components.browser.state.store.BrowserStore
|
|||
import mozilla.components.concept.tabstray.Tab
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.collections.CollectionsDialog
|
||||
import org.mozilla.fenix.collections.show
|
||||
import org.mozilla.fenix.components.TabCollectionStorage
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.components.bookmarks.BookmarksUseCase
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
|
@ -42,6 +44,9 @@ class NavigationInteractorTest {
|
|||
private val context: Context = mockk(relaxed = true)
|
||||
private val collectionStorage: TabCollectionStorage = mockk(relaxed = true)
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
store = BrowserStore(initialState = BrowserState(tabs = listOf(testTab)))
|
||||
|
|
|
@ -31,8 +31,10 @@ import mozilla.components.feature.tabs.TabsUseCases
|
|||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.helpers.DisableNavGraphProviderAssertionRule
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
|
||||
|
@ -68,6 +70,9 @@ class DefaultTabTrayControllerTest {
|
|||
private val tab1 = createTab(url = "http://firefox.com", id = "5678")
|
||||
private val tab2 = createTab(url = "http://mozilla.org", id = "1234")
|
||||
|
||||
@get:Rule
|
||||
val disableNavGraphProviderAssertionRule = DisableNavGraphProviderAssertionRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockkStatic("org.mozilla.fenix.ext.SessionManagerKt")
|
||||
|
|
|
@ -122,6 +122,9 @@ mozilla-detekt-rules:
|
|||
excludes: "**/*Test.kt, **/*Spec.kt, **/test/**, **/androidTest/**"
|
||||
MozillaUseLazyMonitored:
|
||||
active: true
|
||||
MozillaNavigateCheck:
|
||||
active: true
|
||||
excludes: "**/*Test.kt, **/*Spec.kt, **/test/**, **/androidTest/**"
|
||||
|
||||
empty-blocks:
|
||||
active: true
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Config
|
|||
import io.gitlab.arturbosch.detekt.api.RuleSet
|
||||
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
||||
import org.mozilla.fenix.detektrules.perf.MozillaBannedPropertyAccess
|
||||
import org.mozilla.fenix.detektrules.perf.MozillaNavigateCheck
|
||||
import org.mozilla.fenix.detektrules.perf.MozillaStrictModeSuppression
|
||||
import org.mozilla.fenix.detektrules.perf.MozillaRunBlockingCheck
|
||||
import org.mozilla.fenix.detektrules.perf.MozillaUseLazyMonitored
|
||||
|
@ -22,7 +23,8 @@ class CustomRulesetProvider : RuleSetProvider {
|
|||
MozillaStrictModeSuppression(config),
|
||||
MozillaCorrectUnitTestRunner(config),
|
||||
MozillaRunBlockingCheck(config),
|
||||
MozillaUseLazyMonitored(config)
|
||||
MozillaUseLazyMonitored(config),
|
||||
MozillaNavigateCheck(config)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.detektrules.perf
|
||||
|
||||
import io.gitlab.arturbosch.detekt.api.CodeSmell
|
||||
import io.gitlab.arturbosch.detekt.api.Config
|
||||
import io.gitlab.arturbosch.detekt.api.Debt
|
||||
import io.gitlab.arturbosch.detekt.api.Entity
|
||||
import io.gitlab.arturbosch.detekt.api.Issue
|
||||
import io.gitlab.arturbosch.detekt.api.Rule
|
||||
import io.gitlab.arturbosch.detekt.api.Severity
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
|
||||
private const val VIOLATION_MSG = "If you named a method `navigate`, please rename it to something a bit" +
|
||||
"more specific such as `navigateTo...`. However, if you are trying to invoke the Android NavController.navigate" +
|
||||
"please use `org.mozilla.fenix.ext.NavController.navigateBlockingForAsyncNavGraph`" +
|
||||
"instead. Because using `navigate` directly in the code can lead to the NavGraph not being loaded" +
|
||||
"since it relies on a blocking call done in `navigateBlockingForAsyncNavGraph`."
|
||||
|
||||
/**
|
||||
* A check to prevent the use of `navController.navigate`. Since the NavGraph is loaded dynamically
|
||||
* and asynchronously, there is a check in place to make sure the graph is loaded by wrapping the
|
||||
* `navigate` function. However, using it directly might lead to code that needs the NavGraph being
|
||||
* called before it being inflated.
|
||||
*/
|
||||
class MozillaNavigateCheck(config: Config = Config.empty) : Rule(config) {
|
||||
|
||||
override val issue = Issue(
|
||||
"MozillaNavigateCheck",
|
||||
Severity.Performance,
|
||||
"Prevents us from calling `navController.navigate` instead of the functions that" +
|
||||
"wrap it",
|
||||
Debt.TEN_MINS
|
||||
)
|
||||
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
super.visitCallExpression(expression)
|
||||
|
||||
val calledMethod = expression.calleeExpression?.firstChild?.node?.chars
|
||||
|
||||
//We check for the navigate method and we have to ignore our extension function file, since
|
||||
//we call navigate there
|
||||
if (calledMethod == "navigate" ) {
|
||||
report(CodeSmell(issue, Entity.from(expression), VIOLATION_MSG))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue