gui/pkg/browser/service.go
Snider 7aaabf4b77
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run
Harden GUI storage and browser inputs
2026-04-15 22:51:07 +01:00

86 lines
2.4 KiB
Go

package browser
import (
"context"
"net/url"
"path/filepath"
"strings"
core "dappco.re/go/core"
coreerr "dappco.re/go/core/log"
)
type Options struct{}
type Service struct {
*core.ServiceRuntime[Options]
platform Platform
}
func (s *Service) OnStartup(_ context.Context) core.Result {
openURL := func(_ context.Context, opts core.Options) core.Result {
parsedURL, err := validatedOpenURL(opts.String("url"))
if err != nil {
return core.Result{Value: err, OK: false}
}
if err := s.platform.OpenURL(parsedURL); err != nil {
return core.Result{Value: err, OK: false}
}
return core.Result{OK: true}
}
openFile := func(_ context.Context, opts core.Options) core.Result {
path, err := validatedOpenFilePath(opts.String("path"))
if err != nil {
return core.Result{Value: err, OK: false}
}
if err := s.platform.OpenFile(path); err != nil {
return core.Result{Value: err, OK: false}
}
return core.Result{OK: true}
}
s.Core().Action("browser.openURL", openURL)
s.Core().Action("gui.browser.open", openURL)
s.Core().Action("browser.openFile", openFile)
s.Core().Action("gui.browser.openFile", openFile)
return core.Result{OK: true}
}
func (s *Service) HandleIPCEvents(_ *core.Core, _ core.Message) core.Result {
return core.Result{OK: true}
}
func validatedOpenURL(raw string) (string, error) {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return "", coreerr.E("browser.openURL", "url is required", nil)
}
parsed, err := url.ParseRequestURI(trimmed)
if err != nil {
return "", coreerr.E("browser.openURL", "invalid url", err)
}
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return "", coreerr.E("browser.openURL", "unsupported url scheme: "+parsed.Scheme, nil)
}
if parsed.Host == "" {
return "", coreerr.E("browser.openURL", "url host is required", nil)
}
if parsed.User != nil {
return "", coreerr.E("browser.openURL", "url must not include credentials", nil)
}
return parsed.String(), nil
}
func validatedOpenFilePath(raw string) (string, error) {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return "", coreerr.E("browser.openFile", "path is required", nil)
}
if strings.ContainsRune(trimmed, '\x00') {
return "", coreerr.E("browser.openFile", "path contains a null byte", nil)
}
cleaned := filepath.Clean(trimmed)
if !filepath.IsAbs(cleaned) {
return "", coreerr.E("browser.openFile", "path must be absolute", nil)
}
return cleaned, nil
}