Report a missing browser launcher instead of faking success
`open_in_browser` gated its xdg-open path on `target_os = "linux"`, which is false on Android — that is its own target_os. Android therefore took the fallback arm, which discarded the URL and returned `Ok(())`. Login Flow v2 cannot complete without a browser: the user approves the sign-in there and `auth::poll` waits for that approval. Claiming success meant the UI showed "Approve the sign-in in your browser" with no browser open, the poll waited for an approval that could never arrive, and the worker eventually dropped its channel — surfacing as "sign-in failed unexpectedly", which pointed at the network rather than at the real cause. The server had in fact been contacted successfully. Gate on `unix && !android && !macos` so the arm matches what xdg-open actually implies, and return Unsupported from the fallback. The caller treats it as terminal rather than swallowing it with `let _ =`. Android gets a real Intent-based launcher in the next commit; until then the failure is at least honest about what happened. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -290,7 +290,16 @@ fn spawn_login(weak: slint::Weak<AppWindow>, ctl: Rc<LaunchController>, server:
|
||||
};
|
||||
|
||||
// Open the system browser, never an embedded webview (FR-NC-1).
|
||||
let _ = open_in_browser(&flow.login_url);
|
||||
//
|
||||
// Failing here is terminal: the poll below waits for an approval
|
||||
// that only the browser can give, so carrying on would hang until
|
||||
// the flow expired and then report nothing useful.
|
||||
if let Err(e) = open_in_browser(&flow.login_url) {
|
||||
let _ = tx.send(LoginMessage::Failed(format!(
|
||||
"could not open a browser to approve the sign-in: {e}"
|
||||
)));
|
||||
return;
|
||||
}
|
||||
let _ = tx.send(LoginMessage::AwaitingApproval(flow.login_url.clone()));
|
||||
|
||||
match auth::poll(&client, &flow).await {
|
||||
@@ -526,8 +535,16 @@ async fn fetch_user_id(
|
||||
}
|
||||
|
||||
/// Open a URL in the system browser.
|
||||
///
|
||||
/// Login Flow v2 cannot complete without this: the user approves the sign-in
|
||||
/// in a browser and the poll below waits for that approval. So a platform with
|
||||
/// no way to open one must say so rather than return `Ok(())` — reporting
|
||||
/// success here strands the flow on "Approve the sign-in in your browser" with
|
||||
/// no browser and no explanation.
|
||||
fn open_in_browser(url: &str) -> std::io::Result<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
// Not `target_os = "linux"`: Android is its own target_os, and reached this
|
||||
// arm's `Ok(())` fallback, so the browser silently never opened.
|
||||
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
|
||||
{
|
||||
std::process::Command::new("xdg-open")
|
||||
.arg(url)
|
||||
@@ -536,9 +553,12 @@ fn open_in_browser(url: &str) -> std::io::Result<()> {
|
||||
.spawn()
|
||||
.map(|_| ())
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[cfg(not(all(unix, not(target_os = "android"), not(target_os = "macos"))))]
|
||||
{
|
||||
let _ = url;
|
||||
Ok(())
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Unsupported,
|
||||
"no browser launcher on this platform",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user