Sitelet https://github.com/nextcloud/talk-android/pull/6811
Skip to content

fix(login): resume browser login after returning via the launcher icon - #6811

Open
ToteMeiSter wants to merge 7 commits into
nextcloud:masterfrom
ToteMeiSter:fix/login-resume-after-launcher
Open

ToteMeiSter wants to merge 7 commits into
nextcloud:masterfrom
ToteMeiSter:fix/login-resume-after-launcher

Conversation

@ToteMeiSter

@ToteMeiSter ToteMeiSter commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

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

  • MainActivity is singleTask. A launch from the icon clears the activities above it, including ServerSelectionActivity and BrowserLoginActivity with its ViewModel.
  • MainActivity.handleIntent finds no accounts and routes to the server address screen.
  • Polling of the login flow v2 pollUrl starts only in BrowserLoginActivity. 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/poll is never requested.

Change

  • New 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.
  • BrowserLoginActivityViewModel saves the response after the POST. resumeWebBrowserLogin() polls the saved pollUrl without 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 reopens BrowserLoginActivity in resume mode (KEY_RESUME_BROWSER_LOGIN). Below it in the back stack is the conversation list if accounts exist, otherwise the server address screen.
  • A failed poll request (no network, interrupted connection) is retried after a pause instead of ending the login, so the login 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.
  • The manifest and singleTask are 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

  1. Start adding an account: enter the server address and open the browser login.
  2. Grant access in the browser.
  3. Return to Talk by tapping the launcher icon, not via Recents.
  4. Before: the server address screen. After: the login completes and the account is added.
  5. Repeat with Back from the browser and cancel: no stale login is resumed.
  6. Start the login, switch on airplane mode while the browser is open, return to Talk: the waiting screen stays. Switch airplane mode off and grant access: the login completes.

Unit tests: BrowserLoginActivityViewModelTest (resume without a new startLoginFlow, reset after completion and cancel, an expired login is not resumed, retry through network loss, cancel and expiry during retries), LoginRepositoryTest and NetworkLoginDataSourceTest (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 by 10258697a (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

  • None

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed
  • 🔖 Capability is checked or not needed
  • 🔙 Backport requests are created or not needed: /backport to stable-xx.x
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

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 the Assisted-by: Claude-Code:claude-opus-5-5 trailer.

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>
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 368502ed-9cb3-4e4f-8998-23c68c3d015f
📥 Commits

Reviewing files that changed from the base of the PR and between d2e9fc9 and 13b3acb.

📒 Files selected for processing (2)
  • app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt
  • app/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; 1 remain after this review.


📝 Walkthrough

Walkthrough

The 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 13b3a

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 Review

Security architecture risk: 🟡 Moderate · up to 57902

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

  • Medium · security · inferred: The new authentication handoff lacks flow-scoped cancellation and cleanup. A late initial response can recreate pending state after cancellation while its ViewModel remains alive; with overlapping flows, an older cancellation or poll completion can clear a newer pending record. These conditional races weaken abandonment and recovery guarantees, rather than demonstrating credential theft or identity substitution.
Security review details

Security Blast Radius

  • inferred — The demonstrated scope is authentication continuation and local account handling within one app process. An external launch can trigger the pending-login fallback, but that path does not return the saved token or credentials to the caller. Cross-user, cross-device, or server-wide compromise was not established.

Security Findings and Attack Paths

  • inferred — A cancellation followed by initial-request completion before ViewModel disposal can republish the pending record. A subsequent launch can then resume that abandoned authorization attempt. This requires the timing window and any browser authorization needed for completion; it does not show that an external caller can supply credentials or choose the stored identity.

Trust Boundaries and Controls

  • observed — MainActivity constructs a fresh explicit resume intent without forwarding incoming extras. The resumed response and reauthorization context come from process-local state. Credential updates resolve the returned username and server and require the saved account ID when it is non-null; reauthorization rejects creation of an unrelated new account.

Resilience and Maintainability Implications

  • inferred — Process death discards the handoff rather than leaving durable authentication material. Within a surviving process, unconditional clearing and non-exclusive reads leave overlapping-flow failure containment dependent on activity timing rather than explicit ownership.

Hardening Proposals

  • proposed — Give each pending flow an ownership generation, invalidate that generation on abandonment, and make saving, claiming, and clearing conditional on it. Couple explicit cancellation to the initiating job and guard late publication, while preserving recoverability on launcher-driven activity destruction. Validate these guarantees with delayed-request and overlapping-consumer scenarios.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 55 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: resuming browser login after the user returns to Talk through the launcher icon.
Description check ✅ Passed The description explains the symptom, cause, change, testing, limitations, and related issues. It includes the template sections and checklist; the unchecked backport and milestone items do not make i…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ffb3bdb0-0b2b-4d58-8040-7ee5dd6cc267
📥 Commits

Reviewing files that changed from the base of the PR and between 1e9c2f1 and 5790289.

📒 Files selected for processing (7)
  • app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.kt
  • app/src/main/java/com/nextcloud/talk/account/data/LoginRepository.kt
  • app/src/main/java/com/nextcloud/talk/account/data/PendingBrowserLoginStore.kt
  • app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt
  • app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
  • app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.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; 2 remain after this review.

@mahibi

mahibi commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Hi @ToteMeiSter thank you for your contributions.
We will review them soon

@AndyScherzinger AndyScherzinger added the 3. to review Waiting for reviews label Oct 5, 2026
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>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 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 win

Ignore 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, and handleWebBrowserLogin() calls parseAndLogin() and publishes a post-login state. Return when isLoginCanceled is 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
📥 Commits

Reviewing files that changed from the base of the PR and between 5790289 and 1ddb1f5.

📒 Files selected for processing (2)
  • app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt
  • app/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>
@ToteMeiSter

Copy link
Copy Markdown
Contributor Author

@coderabbitai Re the outside-diff comment "Ignore poll results after explicit cancellation" (review 5432917494): fixed in 3504130. handleWebBrowserLogin returns when isLoginCanceled is set before it calls parseAndLogin, so a poll answered after the cancel neither logs in nor publishes a post-login state. Covered by the test cancel ends the pending login, also when the poll answers after it.

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).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt (1)

288-294: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an active regression test for launcher re-entry.

MainActivityTest.login() only creates an account. It does not populate PendingBrowserLoginStore, re-enter MainActivity, or assert the KEY_RESUME_BROWSER_LOGIN extra. LoginIT contains 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 BrowserLoginActivity receives KEY_RESUME_BROWSER_LOGIN=true.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7cb1bf18-2157-47e3-b646-3e8f0b4e50d2
📥 Commits

Reviewing files that changed from the base of the PR and between 1ddb1f5 and 3504130.

📒 Files selected for processing (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.

@ToteMeiSter

ToteMeiSter commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@coderabbitai Re the nitpick "Add an active regression test for launcher re-entry" (review 5433085011, MainActivity.kt 288-294): not added in this PR, on purpose.

  • MainActivity has no unit test setup: it is Dagger-injected and decides the next screen inside a coroutine over UserManager. A Robolectric test would need a fake application component only for this branch.
  • MainActivityTest is an instrumented test. I can not run instrumented tests locally, and an untested UI test is not something I want to hand to the maintainers.
  • The resume logic itself is covered by BrowserLoginActivityViewModelTest (pending login saved, resumed once without a new login request, cleared after poll end, cancel, failure, and expiry). The MainActivity part is a three-way branch plus an intent with KEY_RESUME_BROWSER_LOGIN.

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).

@ToteMeiSter

Copy link
Copy Markdown
Contributor Author

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 stable-25.0.x (e.g. for 25.0.3)? The bug is present in v25.0.2.

Suggested command for a maintainer after merge: /backport to stable-25.0.x

This comment was drafted with AI assistance (Claude Code).

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown

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 all

Length 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.xml

Length of output: 29832


@ToteMeiSter Thanks for the clarification. I checked the current code and test source.

  • Cancellation finding addressed: handleWebBrowserLogin() checks isLoginCanceled before clearing pending state or calling parseAndLogin(). The regression test supplies a successful poll result after cancellation and checks that no login or post-login state follows. I did not run the tests.
  • Overlapping-flow concern withdrawn for this PR: The launcher-return path destroys the previous activity and cancels its ViewModel scope. Polling rethrows CancellationException before clearing pending state. Together with the late-response guards, this supports your explanation. A per-flow generation counter is not required for the flows covered here.

✏️ Learnings added
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:44:14.786Z
Learning: In nextcloud/talk-android, the browser-login launcher-return flow uses singleTask MainActivity to destroy the previous BrowserLoginActivity before resuming its pending login. BrowserLoginActivityViewModel runs polling in viewModelScope and rethrows CancellationException before clearing PendingBrowserLoginStore. Explicit cancellation also guards late initial responses and late poll results with isLoginCanceled. Do not require a per-flow generation counter solely for overlapping old and resumed login flows in this lifecycle path unless a reachable overlap is demonstrated.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


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.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown

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 all

Length 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/test

Length of output: 18199


@ToteMeiSter Thanks for the clarification. I withdraw the nitpick as a requirement for this PR.

I checked the source. MainActivity uses application-component injection and coroutine-based routing through UserManager. MainActivityTest is an instrumented test. BrowserLoginActivityViewModelTest covers the resume and pending-state cases you listed. I did not run the tests.

Those unit tests do not exercise launcher re-entry through MainActivity. Your reported device check covers that path manually. This is a reasonable test scope for this bug fix. Extracting the screen decision can remain an optional follow-up if a maintainer requests it.


✏️ Learnings added
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:44:59.813Z
Learning: For nextcloud/talk-android PR #6811, MainActivity.kt uses application-component injection and coroutine-based routing through UserManager. MainActivityTest.kt is an instrumented test, and the contributor cannot run instrumented tests locally. BrowserLoginActivityViewModelTest.kt covers pending login persistence, resumption without a new login request, duplicate polling, completion, cancellation, failure, and expiry. The contributor reports checking launcher re-entry on a device. Do not require new activity test infrastructure solely for this PR's launcher-routing branch; extracting the screen decision for unit testing is an optional maintainer-requested follow-up.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:44:15.005Z
Learning: In nextcloud/talk-android, the browser-login launcher-return flow uses singleTask MainActivity to destroy the previous BrowserLoginActivity before resuming its pending login. BrowserLoginActivityViewModel runs polling in viewModelScope and rethrows CancellationException before clearing PendingBrowserLoginStore. Explicit cancellation also guards late initial responses and late poll results with isLoginCanceled. Do not require a per-flow generation counter solely for overlapping old and resumed login flows in this lifecycle path unless a reachable overlap is demonstrated.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown

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.kt

Length of output: 21064


@ToteMeiSter Thanks for the clarification. I withdraw the launcher re-entry test nitpick as a requirement for this PR.

I checked the source. MainActivity uses application-component injection and coroutine-based routing through UserManager. MainActivityTest is an instrumented test. BrowserLoginActivityViewModelTest covers the pending-login and resume cases you listed. I did not run the tests.

The ViewModel tests do not exercise launcher re-entry through MainActivity. Your previously reported device check covers that path manually. I used the existing learning about that check and your test constraints.

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 used
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:44:59.916Z
Learning: For nextcloud/talk-android PR #6811, MainActivity.kt uses application-component injection and coroutine-based routing through UserManager. MainActivityTest.kt is an instrumented test, and the contributor cannot run instrumented tests locally. BrowserLoginActivityViewModelTest.kt covers pending login persistence, resumption without a new login request, duplicate polling, completion, cancellation, failure, and expiry. The contributor reports checking launcher re-entry on a device. Do not require new activity test infrastructure solely for this PR's launcher-routing branch; extracting the screen decision for unit testing is an optional maintainer-requested follow-up.

You are interacting with an AI system.

@ToteMeiSter

Copy link
Copy Markdown
Contributor Author

@coderabbitai Correction: the launcher re-entry path through MainActivity has not been checked on a device yet. The first version of my comment said so by mistake; I edited it. Please do not keep a learning that it was device-checked.

Drafted with AI assistance (Claude Code).

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@ToteMeiSter Thanks for the correction. My earlier replies incorrectly stated that launcher re-entry through MainActivity was device-checked. That path has not been checked on a device yet. The ViewModel tests do not verify that activity path.

The tags below request replacement of the inaccurate learning. You can also delete specific learnings from the CodeRabbit UI Learnings page.


✏️ Learnings added
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:47:01.814Z
Learning: For nextcloud/talk-android PR #6811, ToteMeiSter clarified that launcher re-entry through MainActivity has not been checked on a device yet; the earlier claim was a mistake. MainActivity uses application-component injection and coroutine-based routing through UserManager. MainActivityTest is an instrumented test, which the contributor cannot run locally. BrowserLoginActivityViewModelTest covers pending login persistence, resumption without a new login request, duplicate polling, completion, cancellation, failure, and expiry, but does not exercise launcher re-entry through MainActivity. Do not require new activity test infrastructure solely for this PR's launcher-routing branch; extracting the screen decision for unit testing is an optional maintainer-requested follow-up.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


⛔ Learnings removed
Learnt from: ToteMeiSter
URL: https://github.com/nextcloud/talk-android/pull/6811

Timestamp: 2026-10-06T18:44:59.916Z
Learning: For nextcloud/talk-android PR #6811, MainActivity.kt uses application-component injection and coroutine-based routing through UserManager. MainActivityTest.kt is an instrumented test, and the contributor cannot run instrumented tests locally. BrowserLoginActivityViewModelTest.kt covers pending login persistence, resumption without a new login request, duplicate polling, completion, cancellation, failure, and expiry. The contributor reports checking launcher re-entry on a device. Do not require new activity test infrastructure solely for this PR's launcher-routing branch; extracting the screen decision for unit testing is an optional maintainer-requested follow-up.

You 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>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 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 win

Return null for an empty HTTP 200 response.

If the poll returns HTTP 200 without a body, this branch creates LoginCompletion(200, "", "", ""). LoginRepository.pollLogin treats 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
📥 Commits

Reviewing files that changed from the base of the PR and between 3504130 and 1025869.

📒 Files selected for processing (7)
  • app/src/main/java/com/nextcloud/talk/account/BrowserLoginActivity.kt
  • app/src/main/java/com/nextcloud/talk/account/data/LoginRepository.kt
  • app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt
  • app/src/main/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModel.kt
  • app/src/test/java/com/nextcloud/talk/account/viewmodels/BrowserLoginActivityViewModelTest.kt
  • app/src/test/java/com/nextcloud/talk/login/data/LoginRepositoryTest.kt
  • app/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>
@ToteMeiSter

Copy link
Copy Markdown
Contributor Author

@coderabbitai Regarding the outside-diff comment on NetworkLoginDataSource.kt:147-155 (empty HTTP 200 answer): fixed in d2e9fc9. A 200 without a body now returns null and ends the poll as unusable; other statuses without a body still mean "not confirmed yet". Covered by testing performLoginFlowV2 empty 200 response in NetworkLoginDataSourceTest.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 44753126-30cb-4935-ade2-16553cabfa3e
📥 Commits

Reviewing files that changed from the base of the PR and between 1025869 and d2e9fc9.

📒 Files selected for processing (2)
  • app/src/main/java/com/nextcloud/talk/account/data/network/NetworkLoginDataSource.kt
  • app/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.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown

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.kt

Length of output: 8092


@ToteMeiSter Thanks for the fix. I checked the current source.

  • performLoginFlowV2() returns null for an HTTP 200 response with an empty or missing body. pollLogin() then ends polling.
  • Other statuses with an empty or missing body retain their status, so polling continues.
  • testing performLoginFlowV2 empty 200 response asserts that an empty HTTP 200 response returns null.

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>
@ToteMeiSter

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2. developing Work in progress 3. to review Waiting for reviews AI assisted

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants