fleet/pkg/open/open_linux.go
Lucas Manuel Rodriguez c81117b9b2
Add Fleet Desktop support for Wayland display sessions (#25998)
For #19043.

See the versions and distributions tested during development on the QA
notes of #19043.

---

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] A detailed QA plan exists on the associated ticket (if it isn't
there, work with the product group's QA engineer to add it)
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Orbit runs on macOS, Linux and Windows. Check if the orbit
feature/bugfix should only apply to one platform (`runtime.GOOS`).
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [X] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
2025-02-05 14:00:13 -03:00

65 lines
2 KiB
Go

package open
import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
"github.com/fleetdm/fleet/v4/orbit/pkg/platform"
"github.com/rs/zerolog/log"
)
func browser(url string) error {
// xdg-open requires XAUTHORITY set when running on a Wayland session (compatibility mode).
// We get XAUTHORITY from the Xwayland process environment.
//
// We have to do this here instead of when executing fleet-desktop because the Xwayland process
// may not be running yet when orbit is executing fleet-desktop.
xAuthority, err := getXWaylandAuthority()
log.Info().Str("XAUTHORITY", xAuthority).Err(err).Msg("Xwayland process")
if err == nil {
os.Setenv("XAUTHORITY", xAuthority)
}
// xdg-open is available on most Linux-y systems
cmd := exec.Command("xdg-open", url)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// Must be asynchronous (Start, not Run) because xdg-open will continue running
// and block this goroutine if it was the process that opened the browser.
if err := cmd.Start(); err != nil {
return fmt.Errorf("xdg-open failed to start: %w", err)
}
go func() {
// We must call wait to avoid defunct processes.
cmd.Wait() //nolint:errcheck
}()
return nil
}
// getXWaylandAuthority retrieves the X authority file path from
// the running XWayland process environment.
func getXWaylandAuthority() (xAuthorityPath string, err error) {
xWaylandProcess, err := platform.GetProcessByName("Xwayland")
if err != nil {
return "", fmt.Errorf("get process by name: %w", err)
}
executablePath, err := xWaylandProcess.Exe()
if err != nil {
return "", fmt.Errorf("get executable path: %w", err)
}
if executablePath != "/usr/bin/Xwayland" {
return "", fmt.Errorf("invalid Xwayland path: %q", executablePath)
}
envs, err := xWaylandProcess.Environ()
if err != nil {
return "", fmt.Errorf("get environment: %w", err)
}
for _, env := range envs {
if strings.HasPrefix(env, "XAUTHORITY=") {
return strings.TrimPrefix(env, "XAUTHORITY="), nil
}
}
return "", errors.New("XAUTHORITY not found")
}