tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit c26815f243d858c4097554f2879a8ff004f1dae8
parent 3a6d85e46efe2c20748ba17e33f50f9fab584845
Author: pollymce <pmceldowney@mozilla.com>
Date:   Fri, 14 Nov 2025 11:26:50 +0000

Bug 1999784 - fix IllegalStateException when editing saved passwords. r=android-reviewers,mcarare,007

The 'edit login' part of LoginsMiddleware needs to execute on the main thread. Previously this worked because the LoginStore uses UIStore, which used to force you onto the main thread. It no longer does this (since https://phabricator.services.mozilla.com/D268398): actions are dispatched on whatever current thread you are using.
Some login actions are dispatched from an IO thread. So we need to explicitly launch the edit login part back onto the main thread.

Differential Revision: https://phabricator.services.mozilla.com/D272437

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/ui/LoginsMiddleware.kt | 35+++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/ui/LoginsMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/logins/ui/LoginsMiddleware.kt @@ -43,7 +43,8 @@ internal class LoginsMiddleware( private val clipboardManager: ClipboardManager?, ) : Middleware<LoginsState, LoginsAction> { - private val scope = CoroutineScope(ioDispatcher) + private val ioScope = CoroutineScope(ioDispatcher) + private val mainScope = CoroutineScope(Dispatchers.Main) @Suppress("LongMethod", "CyclomaticComplexMethod") override fun invoke( @@ -71,7 +72,7 @@ internal class LoginsMiddleware( getNavController().navigate(LoginsDestinations.EDIT_LOGIN) } is LoginDeletionDialogAction.DeleteTapped -> { - scope.launch { + ioScope.launch { preReductionState.loginsLoginDetailState?.login?.guid?.let { loginsStorage.delete( it, @@ -84,7 +85,7 @@ internal class LoginsMiddleware( } } } - is LoginsListSortMenuAction -> scope.launch { + is LoginsListSortMenuAction -> ioScope.launch { persistLoginsSortOrder(context.store.state.sortOrder) } is LearnMoreAboutSync -> { @@ -133,7 +134,7 @@ internal class LoginsMiddleware( } } - private fun Store<LoginsState, LoginsAction>.loadLoginsList() = scope.launch { + private fun Store<LoginsState, LoginsAction>.loadLoginsList() = ioScope.launch { val loginItems = arrayListOf<LoginItem>() loginsStorage.list().forEach { login -> @@ -174,7 +175,7 @@ internal class LoginsMiddleware( } private fun Store<LoginsState, LoginsAction>.handleAddLogin() = - scope.launch { + ioScope.launch { val host = state.loginsAddLoginState?.host ?: "" val newLoginToAdd = LoginEntry( origin = host, @@ -201,14 +202,14 @@ internal class LoginsMiddleware( } } - private fun handleLoginsDetailsBackPressed() = scope.launch { + private fun handleLoginsDetailsBackPressed() = ioScope.launch { withContext(Dispatchers.Main) { getNavController().navigate(LoginsDestinations.LIST) } } private fun Store<LoginsState, LoginsAction>.handleEditLogin(loginItem: LoginItem) = - scope.launch { + ioScope.launch { val updatedLogin = LoginEntry( origin = loginItem.url, formActionOrigin = loginItem.url, @@ -219,16 +220,18 @@ internal class LoginsMiddleware( try { val loginEdited = loginsStorage.update(loginItem.guid, updatedLogin) - dispatch( - LoginClicked( - LoginItem( - guid = loginEdited.guid, - url = loginEdited.origin, - username = loginEdited.username, - password = loginEdited.password, + mainScope.launch { + dispatch( + LoginClicked( + LoginItem( + guid = loginEdited.guid, + url = loginEdited.origin, + username = loginEdited.username, + password = loginEdited.password, + ), ), - ), - ) + ) + } } catch (exception: LoginsApiException) { exception.printStackTrace() }