Commit Graph
5 Commits
Author SHA1 Message Date
vicrodh 7ea01a7e67 fix(startup): bound and cancel the Linux instance probe
Use one two-second deadline across native Unix connect, D-Bus authentication, name ownership and URL/window forwarding. Own and shut down the transport on cancellation, preserve unconfirmed links, and keep the primary server alive.

Cover stalled and delayed phases, filesystem/abstract buses, ownership release and early UI handoff with isolated fixtures. All 733 Qt tests pass; async-io features remain unchanged.

cx
2026-09-06 05:05:27 -06:00
vicrodh 39ba3282f5 fix(ci): eliminate test-crates build warnings
Correct dead platform declarations, stale rustdoc and test warnings; validate complete gettext headers. Install LLD in the Qt job and explicitly validate committed shader packs without rebaking them. Keep the independent shader bake gate and add three build-policy tests.

The full local gate passed 2398 workspace tests and 715 Qt tests, QML audits, shader baking and the isolated offscreen smoke without compiler, rustdoc or gettext warnings.

cx
2026-09-05 20:31:05 -06:00
vicrodh 4ac6b4006e feat(integrations): make the qobuzapp:// handler a setting
Claiming the official client's `qobuzapp://` scheme was a side effect
of installing. On Linux that displaces nobody; on macOS and Windows the
official client registers the same scheme, and on Windows — where QBZ
is only starting to be adopted — taking the browser's links over at
install time is not a reasonable default. `qbz://` (our own scheme)
stays registered unconditionally.

Settings > Integrations > "Open Qobuz links in QBZ" (link_handler_qt,
pref `qobuz_links_enabled` beside the other Integrations opt-ins),
default on for Linux/macOS and OFF on Windows. The registration moves
only when the toggle is flipped; the one startup reconciliation is
conservative — a claim pointing at this executable while the setting is
off (the 2.0.x MSI wrote one) is dropped, nothing is ever claimed on its
own.

Windows writes/removes HKCU\Software\Classes\qobuzapp (deleting only a
tree whose command names this exe); macOS uses Launch Services and hands
the default back to the first other handler on off; Linux runs xdg-mime
on. The MSI no longer registers qobuzapp and the workflow's protocol
checks cover qbz only. The Windows and macOS arms build on their
platform gates, not on this box.

cc
2026-09-04 13:10:42 -06:00
vicrodh afa32d9bba feat(windows): single instance and protocol deep links
The Windows sibling of single_instance_qt.rs. Same three entry points and the
same present-or-defer behaviour, so main.rs reads identically on both.

A named mutex arbitrates and a named pipe carries the message, because those
are different problems. CreateMutexW answers "did it already exist" atomically,
with no window for a second launch to slip through. A pipe cannot be asked that
without FILE_FLAG_FIRST_PIPE_INSTANCE, and QLocalServer never passes it
(PIPE_UNLIMITED_INSTANCES), so two processes could both believe they were the
server.

The plan asked for QLocalServer here, which meant a new Q_OBJECT file in the
moc list and .qt_module("Network"). A raw named pipe is the same primitive
underneath with none of that build surface, for a protocol two verbs long.

The pipe name is QUALIFIED BY SESSION ID, and that is not cosmetic: the mutex
is `Local\`, which is per-session, while pipe names are machine-global. With
one fixed name and two users signed in, each takes its own mutex but only the
first creates the pipe -- the second primary then serves nothing and ITS later
launches would forward to the OTHER USER'S process. PIPE_REJECT_REMOTE_CLIENTS
because the namespace is reachable over SMB and nothing about a second launch
is remote.

What arrives on the pipe is VALIDATED before it is acted on. It is not argv:
any process running as this user can write a line, and the payload otherwise
went straight to link resolution. The read is bounded at 4 KB for the same
reason.

`qbz://` is rewritten to `qobuzapp://` rather than taught downstream. The
resolver knows qobuzapp and the Qobuz web shapes and nothing else -- a live
test of the forwarding path came back "unsupported or invalid music link" for
a qbz:// URL, and a test in this file already pinned that is_qobuz_link
excludes it. The two carry the same album/track/artist shape, so a prefix swap
is the whole translation, and the MSI's registration finally means something.

A parse alone is not a gate: Url::parse("qbz://") SUCCEEDS, a valid scheme with
an empty everything, so the check requires a non-empty authority -- which is
where every accepted shape carries its target.

The URL validation in select_link is Windows-gated. ShellExecute can split a
link across argv there; Linux and macOS have accepted whatever matched the
prefix since this shipped, and tightening that from a Windows port would change
behaviour on platforms that never asked.

present_or_defer re-reads UI_READY after publishing PENDING_PRESENT. bind_ui
can flip the flag and run its own swap in between, leaving the pending bit set
with nobody to consume it and a second launch looking ignored.

Verified on the box: a second launch carrying a deep link exits 0 in about four
milliseconds, the primary logs the handoff and resolves the rewritten URL.
571 tests pass.

cc
2026-08-27 17:42:53 -06:00
vicrodh edcb12b8a1 feat(qt): close migration parity gaps
cx
2026-08-26 11:11:50 -06:00