For #12565: Pass passwordsStorage instead of context in constructor.
parent
87a7b6f9ec
commit
048f6a49fe
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue