1
0
Fork 0

For #12565: Pass passwordsStorage instead of context in constructor.

master
mcarare 2020-07-29 18:25:00 +03:00 committed by Emily Kager
parent 87a7b6f9ec
commit 048f6a49fe
5 changed files with 34 additions and 33 deletions

View File

@ -4,7 +4,6 @@
package org.mozilla.fenix.settings.logins.controller package org.mozilla.fenix.settings.logins.controller
import android.content.Context
import android.util.Log import android.util.Log
import androidx.navigation.NavController import androidx.navigation.NavController
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
@ -18,8 +17,8 @@ import mozilla.components.concept.storage.Login
import mozilla.components.service.sync.logins.InvalidRecordException import mozilla.components.service.sync.logins.InvalidRecordException
import mozilla.components.service.sync.logins.LoginsStorageException import mozilla.components.service.sync.logins.LoginsStorageException
import mozilla.components.service.sync.logins.NoSuchRecordException import mozilla.components.service.sync.logins.NoSuchRecordException
import mozilla.components.service.sync.logins.SyncableLoginsStorage
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.settings.logins.LoginsAction import org.mozilla.fenix.settings.logins.LoginsAction
import org.mozilla.fenix.settings.logins.LoginsFragmentStore import org.mozilla.fenix.settings.logins.LoginsFragmentStore
import org.mozilla.fenix.settings.logins.fragment.EditLoginFragmentDirections import org.mozilla.fenix.settings.logins.fragment.EditLoginFragmentDirections
@ -29,20 +28,19 @@ import org.mozilla.fenix.settings.logins.mapToSavedLogin
* Controller for all saved logins interactions with the password storage component * Controller for all saved logins interactions with the password storage component
*/ */
open class SavedLoginsStorageController( open class SavedLoginsStorageController(
private val context: Context, private val passwordsStorage: SyncableLoginsStorage,
private val viewLifecycleScope: CoroutineScope, private val viewLifecycleScope: CoroutineScope,
private val navController: NavController, private val navController: NavController,
private val loginsFragmentStore: LoginsFragmentStore private val loginsFragmentStore: LoginsFragmentStore
) { ) {
private suspend fun getLogin(loginId: String): Login? = private suspend fun getLogin(loginId: String): Login? = passwordsStorage.get(loginId)
context.components.core.passwordsStorage.get(loginId)
fun delete(loginId: String) { fun delete(loginId: String) {
var deleteLoginJob: Deferred<Boolean>? = null var deleteLoginJob: Deferred<Boolean>? = null
val deleteJob = viewLifecycleScope.launch(Dispatchers.IO) { val deleteJob = viewLifecycleScope.launch(Dispatchers.IO) {
deleteLoginJob = async { deleteLoginJob = async {
context.components.core.passwordsStorage.delete(loginId) passwordsStorage.delete(loginId)
} }
deleteLoginJob?.await() deleteLoginJob?.await()
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -61,7 +59,7 @@ open class SavedLoginsStorageController(
viewLifecycleScope.launch(Dispatchers.IO) { viewLifecycleScope.launch(Dispatchers.IO) {
saveLoginJob = async { saveLoginJob = async {
// must retrieve from storage to get the httpsRealm and formActionOrigin // must retrieve from storage to get the httpsRealm and formActionOrigin
val oldLogin = context.components.core.passwordsStorage.get(loginId) val oldLogin = passwordsStorage.get(loginId)
// Update requires a Login type, which needs at least one of // Update requires a Login type, which needs at least one of
// httpRealm or formActionOrigin // httpRealm or formActionOrigin
@ -95,16 +93,20 @@ open class SavedLoginsStorageController(
private suspend fun save(loginToSave: Login) { private suspend fun save(loginToSave: Login) {
try { try {
context.components.core.passwordsStorage.update(loginToSave) passwordsStorage.update(loginToSave)
} catch (loginException: LoginsStorageException) { } catch (loginException: LoginsStorageException) {
when (loginException) { when (loginException) {
is NoSuchRecordException, is NoSuchRecordException,
is InvalidRecordException -> { is InvalidRecordException -> {
Log.e("Edit login", Log.e(
"Failed to save edited login.", loginException) "Edit login",
"Failed to save edited login.", loginException
)
} }
else -> Log.e("Edit login", else -> Log.e(
"Failed to save edited login.", loginException) "Edit login",
"Failed to save edited login.", loginException
)
} }
} }
} }
@ -124,7 +126,7 @@ open class SavedLoginsStorageController(
val fetchLoginJob = viewLifecycleScope.launch(Dispatchers.IO) { val fetchLoginJob = viewLifecycleScope.launch(Dispatchers.IO) {
deferredLogin = async { deferredLogin = async {
val login = getLogin(loginId) val login = getLogin(loginId)
context.components.core.passwordsStorage.getPotentialDupesIgnoringUsername(login!!) passwordsStorage.getPotentialDupesIgnoringUsername(login!!)
} }
val fetchedDuplicatesList = deferredLogin?.await() val fetchedDuplicatesList = deferredLogin?.await()
fetchedDuplicatesList?.let { list -> fetchedDuplicatesList?.let { list ->
@ -149,7 +151,7 @@ open class SavedLoginsStorageController(
var deferredLogin: Deferred<List<Login>>? = null var deferredLogin: Deferred<List<Login>>? = null
val fetchLoginJob = viewLifecycleScope.launch(Dispatchers.IO) { val fetchLoginJob = viewLifecycleScope.launch(Dispatchers.IO) {
deferredLogin = async { deferredLogin = async {
context.components.core.passwordsStorage.list() passwordsStorage.list()
} }
val fetchedLoginList = deferredLogin?.await() val fetchedLoginList = deferredLogin?.await()
@ -177,7 +179,7 @@ open class SavedLoginsStorageController(
var deferredLogins: Deferred<List<Login>>? = null var deferredLogins: Deferred<List<Login>>? = null
val fetchLoginsJob = viewLifecycleScope.launch(Dispatchers.IO) { val fetchLoginsJob = viewLifecycleScope.launch(Dispatchers.IO) {
deferredLogins = async { deferredLogins = async {
context.components.core.passwordsStorage.list() passwordsStorage.list()
} }
val logins = deferredLogins?.await() val logins = deferredLogins?.await()
logins?.let { logins?.let {

View File

@ -24,6 +24,7 @@ import mozilla.components.support.ktx.android.view.hideKeyboard
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.redirectToReAuth import org.mozilla.fenix.ext.redirectToReAuth
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
@ -79,7 +80,7 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
interactor = EditLoginInteractor( interactor = EditLoginInteractor(
SavedLoginsStorageController( SavedLoginsStorageController(
context = requireContext(), passwordsStorage = requireContext().components.core.passwordsStorage,
viewLifecycleScope = viewLifecycleOwner.lifecycleScope, viewLifecycleScope = viewLifecycleOwner.lifecycleScope,
navController = findNavController(), navController = findNavController(),
loginsFragmentStore = loginsFragmentStore loginsFragmentStore = loginsFragmentStore

View File

@ -94,7 +94,7 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) {
interactor = LoginDetailInteractor( interactor = LoginDetailInteractor(
SavedLoginsStorageController( SavedLoginsStorageController(
context = requireContext(), passwordsStorage = requireContext().components.core.passwordsStorage,
viewLifecycleScope = viewLifecycleOwner.lifecycleScope, viewLifecycleScope = viewLifecycleOwner.lifecycleScope,
navController = findNavController(), navController = findNavController(),
loginsFragmentStore = savedLoginsStore loginsFragmentStore = savedLoginsStore

View File

@ -101,7 +101,7 @@ class SavedLoginsFragment : Fragment() {
) )
savedLoginsStorageController = savedLoginsStorageController =
SavedLoginsStorageController( SavedLoginsStorageController(
context = requireContext(), passwordsStorage = requireContext().components.core.passwordsStorage,
viewLifecycleScope = viewLifecycleOwner.lifecycleScope, viewLifecycleScope = viewLifecycleOwner.lifecycleScope,
navController = findNavController(), navController = findNavController(),
loginsFragmentStore = savedLoginsStore loginsFragmentStore = savedLoginsStore

View File

@ -4,7 +4,6 @@
package org.mozilla.fenix.settings.logins package org.mozilla.fenix.settings.logins
import android.content.Context
import android.os.Looper import android.os.Looper
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
@ -17,13 +16,13 @@ import kotlinx.coroutines.MainScope
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestCoroutineScope import kotlinx.coroutines.test.TestCoroutineScope
import mozilla.components.concept.storage.Login import mozilla.components.concept.storage.Login
import mozilla.components.service.sync.logins.SyncableLoginsStorage
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.Components
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.settings.logins.controller.SavedLoginsStorageController import org.mozilla.fenix.settings.logins.controller.SavedLoginsStorageController
import org.robolectric.Shadows.shadowOf import org.robolectric.Shadows.shadowOf
@ -34,7 +33,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(FenixRobolectricTestRunner::class) @RunWith(FenixRobolectricTestRunner::class)
class SavedLoginsStorageControllerTest { class SavedLoginsStorageControllerTest {
private lateinit var components: Components private lateinit var components: Components
private val context: Context = mockk(relaxed = true) private val passwordsStorage: SyncableLoginsStorage = mockk(relaxed = true)
private lateinit var controller: SavedLoginsStorageController private lateinit var controller: SavedLoginsStorageController
private val navController: NavController = mockk(relaxed = true) private val navController: NavController = mockk(relaxed = true)
private val loginsFragmentStore: LoginsFragmentStore = mockk(relaxed = true) private val loginsFragmentStore: LoginsFragmentStore = mockk(relaxed = true)
@ -46,13 +45,12 @@ class SavedLoginsStorageControllerTest {
every { navController.currentDestination } returns NavDestination("").apply { every { navController.currentDestination } returns NavDestination("").apply {
id = R.id.loginDetailFragment id = R.id.loginDetailFragment
} }
coEvery { context.components.core.passwordsStorage.get(any()) } returns loginMock coEvery { passwordsStorage.get(any()) } returns loginMock
every { loginsFragmentStore.dispatch(any()) } returns mockk() every { loginsFragmentStore.dispatch(any()) } returns mockk()
coEvery { context.components.core.passwordsStorage } returns mockk(relaxed = true)
components = mockk(relaxed = true) components = mockk(relaxed = true)
controller = SavedLoginsStorageController( controller = SavedLoginsStorageController(
context = context, passwordsStorage = passwordsStorage,
viewLifecycleScope = MainScope(), viewLifecycleScope = MainScope(),
navController = navController, navController = navController,
loginsFragmentStore = loginsFragmentStore loginsFragmentStore = loginsFragmentStore
@ -68,12 +66,12 @@ class SavedLoginsStorageControllerTest {
fun `WHEN a login is deleted, THEN navigate back to the previous page`() = runBlocking { fun `WHEN a login is deleted, THEN navigate back to the previous page`() = runBlocking {
val loginId = "id" val loginId = "id"
// mock for deleteLoginJob: Deferred<Boolean>? // mock for deleteLoginJob: Deferred<Boolean>?
coEvery { context.components.core.passwordsStorage.delete(any()) } returns true coEvery { passwordsStorage.delete(any()) } returns true
controller.delete(loginId) controller.delete(loginId)
shadow() shadow()
coVerify { context.components.core.passwordsStorage.delete(loginId) } coVerify { passwordsStorage.delete(loginId) }
} }
private fun shadow() { private fun shadow() {
@ -86,11 +84,11 @@ class SavedLoginsStorageControllerTest {
fun `WHEN fetching the login list, THEN update the state in the store`() { fun `WHEN fetching the login list, THEN update the state in the store`() {
val loginId = "id" val loginId = "id"
// for deferredLogin: Deferred<List<Login>>? // for deferredLogin: Deferred<List<Login>>?
coEvery { context.components.core.passwordsStorage.list() } returns listOf() coEvery { passwordsStorage.list() } returns listOf()
controller.fetchLoginDetails(loginId) controller.fetchLoginDetails(loginId)
coVerify { context.components.core.passwordsStorage.list() } coVerify { passwordsStorage.list() }
} }
@Test @Test
@ -103,11 +101,11 @@ class SavedLoginsStorageControllerTest {
httpRealm = "httpRealm", httpRealm = "httpRealm",
formActionOrigin = "" formActionOrigin = ""
) )
coEvery { context.components.core.passwordsStorage.get(any()) } returns loginMock coEvery { passwordsStorage.get(any()) } returns loginMock
controller.save(login.guid!!, login.username, login.password) controller.save(login.guid!!, login.username, login.password)
coVerify { context.components.core.passwordsStorage.get(any()) } coVerify { passwordsStorage.get(any()) }
} }
@Test @Test
@ -121,11 +119,11 @@ class SavedLoginsStorageControllerTest {
formActionOrigin = "" formActionOrigin = ""
) )
coEvery { context.components.core.passwordsStorage.get(any()) } returns login coEvery { passwordsStorage.get(any()) } returns login
// for deferredLogin: Deferred<List<Login>>? // for deferredLogin: Deferred<List<Login>>?
coEvery { coEvery {
context.components.core.passwordsStorage.getPotentialDupesIgnoringUsername(any()) passwordsStorage.getPotentialDupesIgnoringUsername(any())
} returns listOf() } returns listOf()
controller.findPotentialDuplicates(login.guid!!) controller.findPotentialDuplicates(login.guid!!)
@ -133,7 +131,7 @@ class SavedLoginsStorageControllerTest {
shadow() shadow()
coVerify { coVerify {
context.components.core.passwordsStorage.getPotentialDupesIgnoringUsername(login) passwordsStorage.getPotentialDupesIgnoringUsername(login)
} }
} }
} }