86 lines
2.4 KiB
Go
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
|
|
}
|