Commit ab2ea8e6 authored by Mugurell's avatar Mugurell
Browse files

For #13037 - Use email to sign in to fxa if device has no camera

App can be installed on devices with no camera modules. Like Android TV boxes.
Will skip presenting the option to sign in by scanning a qr code in this case
and default to login with email and password.
parent 0f0aee5e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.support.ktx.android.content.hasCamera
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity
@@ -188,7 +189,16 @@ class SettingsFragment : PreferenceFragmentCompat() {

        val directions: NavDirections? = when (preference.key) {
            resources.getString(R.string.pref_key_sign_in) -> {
                // App can be installed on devices with no camera modules. Like Android TV boxes.
                // Let's skip presenting the option to sign in by scanning a qr code in this case
                // and default to login with email and password.
                if (requireContext().hasCamera()) {
                    SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment()
                } else {
                    requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())
                    requireComponents.analytics.metrics.track(Event.SyncAuthUseEmail)
                    null
                }
            }
            resources.getString(R.string.pref_key_search_settings) -> {
                SettingsFragmentDirections.actionSettingsFragmentToSearchEngineFragment()
+22 −2
Original line number Diff line number Diff line
@@ -4,16 +4,21 @@

package org.mozilla.fenix.settings.logins

import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.navigation.NavController
import androidx.preference.Preference
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.feature.accounts.FirefoxAccountsAuthFeature
import mozilla.components.service.fxa.SyncEngine
import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.service.fxa.manager.SyncEnginesStorage
import mozilla.components.support.ktx.android.content.hasCamera
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.settings.logins.fragment.SavedLoginsAuthFragmentDirections

/**
@@ -23,7 +28,9 @@ class SyncLoginsPreferenceView(
    private val syncLoginsPreference: Preference,
    lifecycleOwner: LifecycleOwner,
    accountManager: FxaAccountManager,
    private val navController: NavController
    private val navController: NavController,
    private val accountsAuthFeature: FirefoxAccountsAuthFeature,
    private val metrics: MetricController
) {

    init {
@@ -68,7 +75,15 @@ class SyncLoginsPreferenceView(
        syncLoginsPreference.apply {
            summary = context.getString(R.string.preferences_passwords_sync_logins_sign_in)
            setOnPreferenceClickListener {
                // App can be installed on devices with no camera modules. Like Android TV boxes.
                // Let's skip presenting the option to sign in by scanning a qr code in this case
                // and default to login with email and password.
                if (context.hasCamera()) {
                    navigateToTurnOnSyncFragment()
                } else {
                    navigateToPairWithEmail(context)
                }

                true
            }
        }
@@ -102,4 +117,9 @@ class SyncLoginsPreferenceView(
        val directions = SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
        navController.navigate(directions)
    }

    private fun navigateToPairWithEmail(context: Context) {
        accountsAuthFeature.beginAuthentication(context)
        metrics.track(Event.SyncAuthUseEmail)
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -145,7 +145,9 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() {
            requirePreference(R.string.pref_key_password_sync_logins),
            lifecycleOwner = viewLifecycleOwner,
            accountManager = requireComponents.backgroundServices.accountManager,
            navController = findNavController()
            navController = findNavController(),
            accountsAuthFeature = requireComponents.services.accountsAuthFeature,
            metrics = requireComponents.analytics.metrics
        )

        togglePrefsEnabledWhileAuthenticating(enabled = true)
+34 −2
Original line number Diff line number Diff line
@@ -12,18 +12,24 @@ import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkConstructor
import io.mockk.mockkStatic
import io.mockk.slot
import io.mockk.unmockkConstructor
import io.mockk.unmockkStatic
import io.mockk.verify
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.feature.accounts.FirefoxAccountsAuthFeature
import mozilla.components.service.fxa.SyncEngine
import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.service.fxa.manager.SyncEnginesStorage
import mozilla.components.support.ktx.android.content.hasCamera
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.settings.logins.fragment.SavedLoginsAuthFragmentDirections

class SyncLoginsPreferenceViewTest {
@@ -32,6 +38,8 @@ class SyncLoginsPreferenceViewTest {
    @MockK private lateinit var lifecycleOwner: LifecycleOwner
    @MockK private lateinit var accountManager: FxaAccountManager
    @MockK(relaxed = true) private lateinit var navController: NavController
    @MockK(relaxed = true) private lateinit var accountsAuthFeature: FirefoxAccountsAuthFeature
    @MockK(relaxed = true) private lateinit var metrics: MetricController
    private lateinit var accountObserver: CapturingSlot<AccountObserver>
    private lateinit var clickListener: CapturingSlot<Preference.OnPreferenceClickListener>

@@ -87,9 +95,11 @@ class SyncLoginsPreferenceViewTest {
    }

    @Test
    fun `needs login if account does not exist`() {
    fun `needs login if account does not exist and device has camera`() {
        every { accountManager.authenticatedAccount() } returns null
        every { accountManager.accountNeedsReauth() } returns false
        mockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
        every { any<Context>().hasCamera() } returns true
        createView()

        verify { syncLoginsPreference.summary = "Sign in to Sync" }
@@ -100,6 +110,26 @@ class SyncLoginsPreferenceViewTest {
                SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
            )
        }

        unmockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
    }

    @Test
    fun `needs login if account does not exist and device does not have camera`() {
        every { accountManager.authenticatedAccount() } returns null
        every { accountManager.accountNeedsReauth() } returns false
        createView()
        mockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
        every { any<Context>().hasCamera() } returns false

        verify { syncLoginsPreference.summary = "Sign in to Sync" }
        assertTrue(clickListener.captured.onPreferenceClick(syncLoginsPreference))
        verify {
            accountsAuthFeature.beginAuthentication(any())
            metrics.track(Event.SyncAuthUseEmail)
        }

        unmockkStatic("mozilla.components.support.ktx.android.content.ContextKt")
    }

    @Test
@@ -141,6 +171,8 @@ class SyncLoginsPreferenceViewTest {
        syncLoginsPreference,
        lifecycleOwner,
        accountManager,
        navController
        navController,
        accountsAuthFeature,
        metrics
    )
}