Skip to content

fix(desktop): open the dashboard in the Windows default browser - #109

Open
crazy-daddy wants to merge 3 commits into
JayantDevkar:mainfrom
crazy-daddy:fix/windows-default-browser
Open

crazy-daddy wants to merge 3 commits into
JayantDevkar:mainfrom
crazy-daddy:fix/windows-default-browser

Conversation

@crazy-daddy

@crazy-daddy crazy-daddy commented Oct 12, 2026 •

Copy link
Copy Markdown

Summary

On Windows, the desktop launcher opens the dashboard in Edge (or Chrome/Brave, whichever it finds first) even when the user's default browser is something else. This PR makes it respect the Windows default browser.

Changes

  • _chrome_command() on Windows now asks the shell for the default http handler via AssocQueryStringW(ASSOCF_IS_PROTOCOL, ASSOCSTR_EXECUTABLE, "http", "open") (ctypes). This resolves UserChoice, the HKCR fallback, quoting and %ProgramFiles%-style paths the way Explorer does, instead of probing a fixed Chrome/Edge/Brave list.
  • If the default browser is Chromium-based, it is used for the --app= window. Detection: every Chromium build ships a *_elf.dll (chrome_elf.dll, msedge_elf.dll, …) in the versioned folder next to the exe, whatever the brand. That covers Chrome, Edge, Brave, Vivaldi, Comet, etc. without a name list.
  • If the default is a known non-Chromium browser (e.g. Firefox), _chrome_command() returns None and open_window() falls back to webbrowser.open, a plain tab in the default browser. Previously, the dashboard opened in Edge for these users.
  • If Windows can't resolve a default at all (no association, or a stale path), the previous Chrome/Edge/Brave lookup is kept as the fallback, so those machines still get app mode. A Store-app default that resolves only to the LaunchWinApp.exe broker gets a plain tab in that browser rather than a guess.
  • macOS and Linux behavior is unchanged.

Component

  • API (FastAPI backend)
  • Frontend (SvelteKit dashboard)
  • Captain Hook (hook models)
  • Hook Scripts
  • Documentation
  • CI / Build
  • Desktop launcher (scripts/karma_desktop)

Type

  • Feature (new functionality)
  • Bug fix
  • Refactor (no behavior change)
  • Performance improvement
  • Documentation
  • Tests

Testing

  • scripts/tests pass on Windows (53 passed, 13 skipped as other-OS). The new Windows tests stub only the thin ctypes call and run real-looking answers through the resolution logic: Chromium default → app mode, Firefox default → plain tab, %VAR% path, unquoted path with spaces, lookup failure / empty / LaunchWinApp.exe / missing file → fallback list. One test calls the real AssocQueryStringW on the runner.
  • ruff check / ruff format --check clean
  • Manually tested on Windows 11 with a non-Edge Chromium default (Perplexity Comet): the dashboard opens as a Comet app window instead of Edge
  • Not tested on macOS/Linux (code paths unchanged)

Related Issues

None filed. Companion PR: --silent for windowless server start on Windows.

On Windows the launcher probed a fixed list (Chrome, then Edge, then
Brave) for app mode and never looked at the user's default browser, so
Edge opened even when another browser was the default.

Read the default http handler from the registry instead. If it is
Chromium-based (detected by the *_elf.dll every Chromium build ships),
open it in app mode; otherwise return None so open_window falls back to
webbrowser.open, a plain tab in the default browser.
@crazy-daddy
crazy-daddy marked this pull request as ready for review October 12, 2026 04:26

@JayantDevkar JayantDevkar left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Inline context for reviewers, one note per change area.

Comment thread scripts/karma_desktop/launcher.py Outdated
Comment thread scripts/karma_desktop/launcher.py Outdated
Comment thread scripts/karma_desktop/launcher.py
Comment thread scripts/tests/test_karma_desktop.py Outdated
@JayantDevkar

Copy link
Copy Markdown
Owner

Agreed the hard-coded Edge/Chrome/Brave list is wrong, and the *_elf.dll trick for "is this Chromium" is a nice way to avoid a brand list.

The part I'd like changed is the registry walk. Reading only HKCU\...\http\UserChoice means a machine without that key (fresh or managed Windows, or after an Edge update resets associations) gets None and a plain tab, which is the regression the code you removed was guarding against. There are also a few command shapes the parse doesn't handle (expandable %ProgramFiles% paths, unquoted paths with spaces, Store-installed browsers that register LaunchWinApp.exe). Details on the lines.

Simplest fix I can see: ask Windows for the handler with AssocQueryStringW(ASSOCF_IS_PROTOCOL, ASSOCSTR_EXECUTABLE, "http", "open") through ctypes, which resolves UserChoice, HKCR fallback, quoting and env vars the same way Explorer does, and keep the old Chromium list as a last resort if that call fails. Then a couple of tests that hit the parsing path rather than stubbing it.

I'll approve the CI run so the Windows job executes your tests.

@crazy-daddy

Copy link
Copy Markdown
Author

Thanks for the detailed review, learned something new again.

I went with AssocQueryStringW plus the old list as a fallback, as you suggested; details are on the threads.
All (platform-appropriate) tests pass locally on Windows, and I checked that the real lookup resolves Comet here.
I couldn’t verify that the lookup always returns the real exe for Store-installed browsers (AtlasOS with Store off), so if it answers with LaunchWinApp.exe, the dashboard opens as a plain tab in the default browser rather than guessing that it's chromium or falling back to the list.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants