Repository navigation
fix(login): resume browser login after returning via the launcher icon - #6811
ToteMeiSter wants to merge 7 commits into
Conversation
MainActivity is singleTask, so opening the app by the launcher icon while the browser login is pending clears BrowserLoginActivity and routes to the server selection. The login confirmed in the browser was lost. Keep the unfinished login in memory (20 min, the login flow v2 lifetime) and let MainActivity reopen BrowserLoginActivity in resume mode, which polls the saved response without a new login request or browser launch. Back and the cancel button drop the pending login. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
Codacy flags three returns as a ReturnCount issue. Behaviour is unchanged. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review. 📝 WalkthroughWalkthroughThe change stores an unfinished browser login and its reauthentication details in memory for up to 20 minutes. On startup, the app checks for an active pending login and opens the browser login screen in resume mode. The view model restores the saved login flow and polls without starting another login request. Poll completion and cancellation clear the pending state. Back navigation cancels the login before returning to MainActivity. Tests cover resumption, repeated resume calls, cancellation, and expiration. Priority: ➖ Normal Merge Risk: 🔵 Low · up to A login response arriving just after the 20-minute pending-login window can still complete account login. This is a narrow timing issue; the empty-response handling is fixed, and the remaining expiry risk is bounded. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The normal resume path preserves account identity and keeps login tokens out of persistent storage. However, cancellation and completion are not tied to a particular pending login, so late or overlapping operations can revive an abandoned login or discard another login’s recovery state. No credential disclosure or account takeover was demonstrated. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
ffb3bdb0-0b2b-4d58-8040-7ee5dd6cc267
📒 Files selected for processing (7)
app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.ktapp/src/main/java/com/nextcloud/talk/account/data/LoginRepository.ktapp/src/main/java/com/nextcloud/talk/account/data/PendingBrowserLoginStore.ktapp/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.ktapp/src/main/java/com/nextcloud/talk/activities/MainActivity.ktapp/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.ktapp/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
|
Hi @ToteMeiSter thank you for your contributions. |
A login request that answers after cancelLogin() no longer saves its response, which a later return via the launcher icon would resume. A poll that fails with an unexpected exception ends the pending login with an error instead of leaving it to be resumed; a cancellation of the poll still keeps it pending. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟡 Minor · Ignore poll results after explicit cancellation. · BrowserLoginActivityViewModel.kt:115-129
app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt:115-129
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winIgnore poll results after explicit cancellation.
When the user cancels during polling, the in-flight request can still return HTTP OK before the activity clears its ViewModel scope.
pollLogin()then returns that result, andhandleWebBrowserLogin()callsparseAndLogin()and publishes a post-login state. Return whenisLoginCanceledis true before parsing the result.Suggested fix
} .getOrNull() + if (isLoginCanceled) return@launch // Only reached when the poll ended. If this view model is cleared first, the login stays pending. PendingBrowserLoginStore.clear()
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
d7167285-3f51-4328-81b6-c81f0283cbf6
📒 Files selected for processing (2)
app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.ktapp/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt
- app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
A poll that returns the login data after cancelLogin() no longer logs in or publishes a post-login state. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
@coderabbitai Re the outside-diff comment "Ignore poll results after explicit cancellation" (review 5432917494): fixed in 3504130. Re the retained security concern about overlapping flows: a late initial response after the cancel is covered since 1ddb1f5, and a late poll result by the commit above. A per-flow generation is not added. Only one browser login runs at a time: the activity whose login is resumed was destroyed by the launcher return, which cancels its view model scope before any clear. So an older poll cannot clear the record of a newer one in the flows this PR handles. A generation counter would add state for a race these flows do not reach. Drafted with AI assistance (Claude Code). |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt (1)
288-294: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd an active regression test for launcher re-entry.
MainActivityTest.login()only creates an account. It does not populatePendingBrowserLoginStore, re-enterMainActivity, or assert theKEY_RESUME_BROWSER_LOGINextra.LoginITcontains the only broader login flow, but the class is marked@Ignore.A regression could therefore remove this branch or the resume flag while the active tests still pass. Add a focused active test that simulates launcher re-entry with a pending login and asserts that
BrowserLoginActivityreceivesKEY_RESUME_BROWSER_LOGIN=true.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
7cb1bf18-2157-47e3-b646-3e8f0b4e50d2
📒 Files selected for processing (2)
app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.ktapp/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
|
@coderabbitai Re the nitpick "Add an active regression test for launcher re-entry" (review 5433085011,
If a maintainer prefers it, I can extract the screen decision into a small function with a unit test in a follow-up. Drafted with AI assistance (Claude Code). |
|
This is a bug fix and all CodeRabbit review threads are resolved. Once it is approved and merged, would it be possible to backport it to Suggested command for a maintainer after merge: This comment was drafted with AI assistance (Claude Code). |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
fd '^(BrowserLoginActivityViewModel|BrowserLoginActivityViewModelTest|BrowserLoginActivity|MainActivity|PendingBrowserLoginStore)\.kt$'
ast-grep outline app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt --items all
ast-grep outline app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.kt --items all
ast-grep outline app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt --match 'onCreate|onNewIntent|init' --items all
ast-grep outline app/src/main/java/com/nextcloud/talk/account/data/PendingBrowserLoginStore.kt --items all
ast-grep outline app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt --items allLength of output: 6673 🏁 Script executed: #!/bin/bash
sed -n '24,240p' app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt
sed -n '39,205p' app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.kt
sed -n '36,310p' app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
sed -n '14,90p' app/src/main/java/com/nextcloud/talk/account/data/PendingBrowserLoginStore.kt
ast-grep outline app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt --items all
sed -n '235,330p' app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
rg -n -C3 'singleTask|BrowserLoginActivity|MainActivity' app/src/main/AndroidManifest.xmlLength of output: 29832
✏️ Learnings added
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
fd '^(MainActivity|MainActivityTest|BrowserLoginActivityViewModelTest)\.kt$'
ast-grep outline app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt --items all --match 'onCreate|onNewIntent|init'
ast-grep outline app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt --items all
fd '^MainActivityTest\.kt$' --exec ast-grep outline {} --items allLength of output: 3321 🏁 Script executed: #!/bin/bash
ast-grep outline app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt --items all
sed -n '70,155p' app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
sed -n '235,335p' app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
sed -n '1,100p' app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt
sed -n '36,310p' app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
fd '^MainActivity.*Test\.kt$' app/src/testLength of output: 18199
I checked the source. Those unit tests do not exercise launcher re-entry through ✏️ Learnings added
🧠 Learnings usedYou are interacting with an AI system. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
fd '^(MainActivity|MainActivityTest|BrowserLoginActivityViewModelTest)\.kt$'
ast-grep outline app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt --items all
sed -n '70,155p' app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
sed -n '235,335p' app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
fd '^MainActivityTest\.kt$' --exec ast-grep outline {} --items all
fd '^MainActivityTest\.kt$' --exec sed -n '1,110p' {}
ast-grep outline app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt --items all
sed -n '36,310p' app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.ktLength of output: 21064
I checked the source. The ViewModel tests do not exercise launcher re-entry through This test scope is reasonable for this bug fix. Extracting the screen decision can remain an optional follow-up if a maintainer requests it. 🧠 Learnings usedYou are interacting with an AI system. |
|
@coderabbitai Correction: the launcher re-entry path through Drafted with AI assistance (Claude Code). |
|
Tip For best results, initiate chat on the files or code changes.
The tags below request replacement of the inaccurate learning. You can also delete specific learnings from the CodeRabbit UI Learnings page. ✏️ Learnings added
⛔ Learnings removedYou are interacting with an AI system. |
A failed poll request (no network, interrupted connection) no longer ends the login: it is retried after a pause while the login is pending, so it completes once the network is back. The poll ends for good on an unusable 200 answer, on cancel, or when the login expires after 20 minutes. The waiting screen then closes with a message instead of keeping its spinner. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟡 Minor · Return null for an empty HTTP 200 response. · NetworkLoginDataSource.kt:147-155
app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt:147-155
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReturn null for an empty HTTP 200 response.
If the poll returns HTTP 200 without a body, this branch creates
LoginCompletion(200, "", "", "").LoginRepository.pollLogintreats it as success, so the view model attempts login with empty account details instead of reporting an unusable response. Return null for this case, as the new method contract specifies.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
d43601a8-3b38-4bcc-9c7f-bbd46aa96cb7
📒 Files selected for processing (7)
app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.ktapp/src/main/java/com/nextcloud/talk/account/data/LoginRepository.ktapp/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.ktapp/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.ktapp/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.ktapp/src/test/java/com/nextcloud/talk/login/data/LoginRepositoryTest.ktapp/src/test/java/com/nextcloud/talk/login/data/network/NetworkLoginDataSourceTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
A confirmed poll without the login data is unusable, so it ends the poll instead of being taken as a login with empty account details. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
@coderabbitai Regarding the outside-diff comment on |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
44753126-30cb-4935-ade2-16553cabfa3e
📒 Files selected for processing (2)
app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.ktapp/src/test/java/com/nextcloud/talk/login/data/network/NetworkLoginDataSourceTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
fd '^(NetworkLoginDataSource|NetworkLoginDataSourceTest|LoginRepository)\.kt$'
ast-grep outline app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt --items all --match 'performLoginFlowV2|HTTP'
sed -n '110,195p' app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt
ast-grep outline app/src/test/java/com/nextcloud/talk/login/data/network/NetworkLoginDataSourceTest.kt --items all --match 'empty|performLoginFlowV2'
rg -n -C14 'testing performLoginFlowV2 empty 200 response' app/src/test/java/com/nextcloud/talk/login/data/network/NetworkLoginDataSourceTest.kt
ast-grep outline app/src/main/java/com/nextcloud/talk/account/data/LoginRepository.kt --items all --match 'pollLogin'
rg -n -A65 -B3 'suspend fun pollLogin' app/src/main/java/com/nextcloud/talk/account/data/LoginRepository.ktLength of output: 8092
This addresses the finding. I did not run the tests. You are interacting with an AI system. |
Invalid JSON or a null field in a confirmed poll answer returns null like any other unusable answer, instead of throwing past the poll loop. Assisted-by: Claude-Code:claude-opus-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
@coderabbitai review |
✅ Action performedReview finished.
|
Symptom
Enter the server address, log in in the browser, then return to Talk by tapping the launcher icon. Talk shows the server address screen again and no account is created. Returning via Recents or Back works.
Cause
MainActivityissingleTask. A launch from the icon clears the activities above it, includingServerSelectionActivityandBrowserLoginActivitywith its ViewModel.MainActivity.handleIntentfinds no accounts and routes to the server address screen.pollUrlstarts only inBrowserLoginActivity. That activity is gone, so the login already granted in the browser is lost.This matches the analysis of @hsudbrock in #1512 (Pixel 6 Pro, Android 16): with the launcher icon,
/login/v2/pollis never requested.Change
PendingBrowserLoginStore: keeps the started login flow v2 response and the reauth flags in process memory for 20 minutes. Nothing is written to preferences or the database, because the response contains the poll token.BrowserLoginActivityViewModelsaves the response after the POST.resumeWebBrowserLogin()polls the savedpollUrlwithout a new POST and without opening the browser again. The pending login is cleared on completion, error, cancel, Back and expiry.MainActivity.handleIntent: when a pending login exists, it reopensBrowserLoginActivityin resume mode (KEY_RESUME_BROWSER_LOGIN). Below it in the back stack is the conversation list if accounts exist, otherwise the server address screen.singleTaskare unchanged.Limitation: if the process is killed while the browser is open, the pending login is lost and the user logs in again, as before.
How to test
Unit tests:
BrowserLoginActivityViewModelTest(resume without a newstartLoginFlow, reset after completion and cancel, an expired login is not resumed, retry through network loss, cancel and expiry during retries),LoginRepositoryTestandNetworkLoginDataSourceTest(retry after a failed request).Tested by the reporter on a Huawei DEL-LX9 at fork commit
addf79662, except network loss while waiting: that case failed there and is fixed by10258697a(step 6), which is covered by unit tests only so far and not yet tested on a device.Related
Refs #1512 (closed; the maintainer asked for a new issue for the launcher icon case). Related to #3295 and #6716 by symptom (the server address screen comes back after login); their cause is not confirmed.
🖼️ Screenshots
Not applicable.
🚧 TODO
🏁 Checklist
/backport to stable-xx.x🤖 AI (if applicable)
This change was prepared with Claude Code (claude-opus-5-5). The author reviewed the code and tested it on a device at
addf79662; the network loss fix (step 6) is not yet tested on a device. The commits carry theAssisted-by: Claude-Code:claude-opus-5-5trailer.